Vishwanath
@frozeninretroThis was a question I encountered in one of the frontend interviews. The premise was simple; we need to implement call using bind by using a custom method which can have any name.
Normally, the interviewer would ask you what call/apply/bind
are, and probably ask for a polyfill-like implementation for the same.
The core difference between call
and bind
is that call
executes immediately, whereas we can choose to execute our bound function later on.
const boundFunc = someFunc.bind(obj);
// boundFunc has to be executed later on
someFunc.call(obj);
// Immediate execution
Let's implement it and then break it down into parts to understand it clearly:
customCallImplementation.js
let obj = {
name: 'Jake',
};
function printLastName(lastname) {
console.log(`${this.name} has the lastname ${lastname}`);
}
Function.prototype.myCall = function (thisArg, ...args) {
const result = this.bind(thisArg, ...args);
result(); // Execute it immediately
};
printLastName.myCall(obj, 'Peralta'); // Jake has the lastname Peralta
- We're creating a method called
myCall
and adding it to the Function's prototype. It's not recommended to modify theFunction
prototype, but we're just doing it for the sake of this article. - Our
myCall
method needs two arguments;this
value to call ourprintLastName
function with, and the comma separated arguments that can be passed one-by-one, because that's howFunction.prototype.call()
works. If this is not clear, please refer to the MDN documentation forcall
highlighted in the second line of this article. - We use
Function.prototype.bind
to bind ourprintLastName
function with the giventhis
value, and we immediately execute it, thereby making it work likecall
.
We've successfully created our own custom call method(myCall) and made it work like call
by using bind
. So, both the code snippets do exactly the same thing.
printLastName.call(obj, 'Peralta');
// Jake has the lastname Peralta
printLastName.myCall(obj, 'Peralta');
// Jake has the lastname Peralta