javascript fundamentals
thisprototypespolyfills
Polyfill call and apply
Implement Function.prototype.call and Function.prototype.apply yourself.
What it tests
Whether you really understand this binding, or have only memorised the rules.
The trick is that you cannot use call/apply/bind to write them — you have
to bind this some other way.
The approach
Attach the function as a temporary property of the target object, call it as a method so the implicit binding does the work, then remove it:
Function.prototype.myCall = function (context, ...args) {
context = context || globalThis;
const key = Symbol("fn");
context[key] = this;
const result = context[key](...args);
delete context[key];
return result;
};apply is the same thing with the arguments arriving as an array.
Where it usually goes wrong
- Using a string key.
context.fn = thisclobbers a realfnproperty if the object has one. ASymbolcan't collide. - Not returning the result. Easy to forget once
deleteis in the way. - Forgetting primitives and
null. Non-strictcall(null)binds the global object, and primitives get wrapped.
Full solution
2 files from src/folders/polyfills.
apply.js
const first = {
name: "sourav",
};
function printNames(a, b) {
return this.name + " " + a + " " + b;
}
Function.prototype.myApply = function (thisArgs, args = []) {
const self = thisArgs || globalThis;
const key = Symbol();
self[key] = this;
const result = self[key](...args);
delete self[key];
return result;
};
console.log(printNames.myApply(first, ["hi", "there"]));call.js
const villan = {
name: "sourav",
};
function SayName() {
console.log(this.name);
}
function myCall(fn, thisArgs, ...args) {
thisArgs.fn = fn;
const result = thisArgs.fn(...args);
delete thisArgs.fn;
return result;
}
myCall(SayName, villan);
Function.prototype.myCall = function (thisArgs, ...args) {
const key = Symbol();
thisArgs[key] = this;
const result = thisArgs[key](...args);
delete thisArgs[key];
return result;
};
Function.prototype.myCall = function (thisArgs, ...args) {
const self = thisArgs || globalThis;
const key = Symbol();
self[key] = this;
const result = self[key](...args);
delete self[key];
return result;
};
Function.prototype.myCall = function (thisArgs, ...args) {
return this.apply(thisArgs, args);
};share this post