Implement Function Bind. JavaScript's Function - Prototype.bind Is - by JK - Medium
Implement Function Bind. JavaScript's Function - Prototype.bind Is - by JK - Medium
With the advent of ES6 (ES2015), we will see a decreased explicit use of the
bind method (arrow-functions implicitly bind function to context); but
learning how it works is still of great value.
Here is a simple example of the kind of thing you want to do with bind():
There’s an object jimbot that has two properties: “name” and a method
“greet.”
let jimbot = {
name: 'Jimbot',
greet: function {
alert('Say hello to' + ' ' + this.name);
}
};
You may need to invoke jimbot’s greet method. Since the method refers to
its context, using “this,” whenever you invoke the function, its “this.name”
will always refer to its current context’s name: “Jimbot.”
The setup above becomes a problem when you want to use the greet
method but make it refer to a new object’s context. For example, instead of
printing, “Say hello to Jimbot”, I want it to print, “Say hello to Janice.”
I could write the method over and over again in new objects; but that
prevents us from writing DRY (Don’t Repeat Yourself) code. This is how
function bind solves that problem:
Notice bind() takes two parameters in this example (method, new context).
Function bind has bound jimbot’s greet method to the new object with
“Janice” as the value of the name property.
Here is the same problem, solved using Function.prototype.bind:
let jimbot = {
name: 'Jimbot',
greet: function {
alert('Say hello to' + ' ' + this.name);
}
};
Notice that there is no need to pass in the method in the bind function
parameter. That is because the method is prepended to the bind method
itself:
jimbot.shout.bind ...
2. There’s more: bind, when invoked later on with a new argument (in
this case, with the string “bar”), should “save” the previous
argument “foo” and the current argument “bar” for use in its final
output.
return function() {
}
};
}
};
return function() {
// context is the context passed in above.
return func.apply(context);
}
};
We also established that we will need to use .apply() to apply the context to
the func.
.apply() is better to use here than .call() because .apply() accepts a second
argument, which is array-like whereas .call() accepts a list (which is
unhelpful since we are building an array of arguments for the inner
function. That array-like second argument will serve as the arguments
for func once the applying is complete, so let’s finish scripting it:
return function() {
let currentArgs = [].slice.call(arguments);
let combinedArgs = [].concat(previousArgs, currentArgs);
return func.apply(context, combinedArgs);
}
};
Final Code:
return function() {
let currentArgs = [].slice.call(arguments);
let combinedArgs = [].concat(previousArgs, currentArgs);
return func.apply(context, combinedArgs);
}
};
Function.prototype.bind = function(context) {
// method is attached to the prototype, so just refer to it as
this.
let func = this;
let previousArgs = [].slice.call(arguments, 1);
return function(){
let currentArgs = [].slice.call(arguments);
let combinedArgs = [].concat(previousArgs, currentArgs);
return func.apply(context, combinedArgs);
};
};
JavaScript Lessons: