You can find all the code in this post at repo Github.
Function prototype related challenges
Function.prototype.call()
/**
* @param {any} thisArg
* @param {...*} argArray
* @return {any}
*/
Function.prototype.myCall = function (thisArg, ...argArray) {
const sym = Symbol();
const wrapperObj = Object(thisArg);
Object.defineProperty(wrapperObj, sym, {
enumerable: false,
value: this,
});
return wrapperObj[sym](...argArray);
};
// Usage example
function multiplyAge(multiplier = 1) {
return this.age * multiplier;
}
const mary = {
age: 21,
};
const john = {
age: 42,
};
console.log(multiplyAge.myCall(mary)); // 21
console.log(multiplyAge.myCall(john, 2)); // 84
Function.prototype.apply()
/**
* @param thisArg The object to be used as the this object.
* @param argArray A set of arguments to be passed to the function.
* @return {any}
*/
Function.prototype.myApply = function (thisArg, argArray = []) {
const sym = Symbol();
const wrapperObj = Object(thisArg);
Object.defineProperty(wrapperObj, sym, {
enumerable: false,
value: this,
});
return wrapperObj[sym](...argArray);
};
// Usage example
function multiplyAge(multiplier = 1) {
return this.age * multiplier;
}
const mary = {
age: 21,
};
const john = {
age: 42,
};
console.log(multiplyAge.myApply(mary)); // 21
console.log(multiplyAge.myApply(john, [2])); // 84
Function.prototype.bind()
/**
* @param {any} thisArg
* @param {...*} argArray
* @return {Function}
*/
Function.prototype.myBind = function (thisArg, ...argArray) {
const sym = Symbol();
const wrapperObj = Object(thisArg);
Object.defineProperty(wrapperObj, sym, {
enumerable: false,
value: this,
});
return function (...args) {
return wrapperObj[sym](...argArray, ...args);
};
};
// Usage example
const john = {
age: 42,
getAge: function () {
return this.age;
},
};
const unboundGetAge = john.getAge;
console.log(unboundGetAge()); // undefined
const boundGetAge = john.getAge.myBind(john);
console.log(boundGetAge()); // 42
const jack = {
age: 21,
getAge: function () {
return this.age;
},
};
// For multiple `.bind()` chaining, only the first one would work
const boundJohnGetAge = john.getAge.myBind(john).myBind(jack);
console.log(boundGetAge()); // 42