Skip to main content

Function Methods Polyfill

Call Polyfill

const person = {
sayFullName: function (state, city) {
return `${this.fName} ${this.lName} lives in ${city} ${state}`;
},
};

const john = {
fName: "John",
lName: "Clark",
};

Function.prototype.myCall = function (ctx, ...args) {
if (typeof this !== "function") throw new Error("Not callable");
ctx = ctx || globalThis;
const id = Symbol();
ctx[id] = this;
const result = ctx[id](...args);
delete ctx[id];
return result;
};

console.log(person.sayFullName.myCall(john, "Uttar Pradesh", "Lucknow"));

Apply Polyfill

const person = {
sayFullName: function (state, city) {
return `${this.fName} ${this.lName} lives in ${city} ${state}`;
},
};

const john = {
fName: "John",
lName: "Clark",
};

Function.prototype.myApply = function (ctx, args) {
if (typeof this !== "function") throw new Error("Not callable");
ctx = ctx || globalThis;
const id = Symbol();
ctx[id] = this;
const result = ctx[id](...(args || []));
delete ctx[id];
return result;
};

console.log(person.sayFullName.myApply(john, ["Uttar Pradesh", "Lucknow"]));

Bind Polyfill

const person = {
sayFullName: function (state, city) {
return `${this.fName} ${this.lName} lives in ${city} ${state}`;
},
};

const john = {
fName: "John",
lName: "Clark",
};

Function.prototype.myBind = function (ctx, ...args) {
if (typeof this !== "function") throw new Error("Not callable");
const self = this;
return function (...newArgs) {
return self.apply(ctx, [...args, ...newArgs]);
};
};

console.log(person.sayFullName.bind(john, "Uttar Pradesh")("Lucknow"));

Soft Binding

const softBind = (obj, fn) => {
return function (...args) {
const globalCtx = typeof window !== 'undefined' ? window : globalThis
return fn.apply(
(!this || this === globalCtx) ? obj : this, args
)
}
}

const person = {
empName: 'Alex',
age: 28,
isDisabled: false,
greet: function () {
console.log(`Hi, my name is ${this.empName}.`);
}
}

const bound = softBind(person, person.greet)
bound()

bound.call({ empName: 'Robert' })

Debounce

const debounce = (fn, wait) => {
let timer;
return (...args) => {
if (timer) clearTimeout(timer)
timer = setTimeout(() => fn(...args), wait)
}
}


const callJohn = (name) => {
console.log(`Hi ${name}`);
}


const fn = debounce(() => callJohn('Johnyy'), 2000)
fn()

Throttle

const throttle = (fn, wait) => {
let last = 0
return (...args) => {
const now = Date.now()
if (now - last >= wait) {
last = now
fn(...args)
}
}
}

//OR

const throttle = (fn, wait) => {
let isThrottled = false;

return (...args) => {
if (!isThrottled) {
fn(...args);
isThrottled = true;

setTimeout(() => {
isThrottled = false;
}, wait);
}
};
};

const callJohn = (name) => {
console.log(`Hi ${name}`);
}


const fn = throttle(() => callJohn('Braddd'), 2000)


setTimeout(() => fn(), 1000) //ignored 1000<2000
setTimeout(() => fn(), 1100) //ignored 1000<2000
setTimeout(() => fn(), 1200) //ignored 1000<2000
setTimeout(() => fn(), 2500) //Hi Braddd