0% found this document useful (0 votes)
38 views11 pages

Implement Function Bind. JavaScript's Function - Prototype.bind Is - by JK - Medium

The document discusses the JavaScript Function.prototype.bind method. It explains that bind allows functions to maintain their context when called from different objects. It provides an example of bind solving this problem. It then discusses edge cases like binding previous arguments. Finally, it provides the code to implement bind and lessons about closure, this, and apply vs call.

Uploaded by

vipingoyal1000
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
38 views11 pages

Implement Function Bind. JavaScript's Function - Prototype.bind Is - by JK - Medium

The document discusses the JavaScript Function.prototype.bind method. It explains that bind allows functions to maintain their context when called from different objects. It provides an example of bind solving this problem. It then discusses edge cases like binding previous arguments. Finally, it provides the code to implement bind and lessons about closure, this, and apply vs call.

Uploaded by

vipingoyal1000
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 11

JK 29 Followers About Follow Upgrade

Implement Function Bind


JK Nov 18, 2016 · 5 min read

JavaScript’s Function.prototype.bind is a useful problem-solving tool when


you need to maintain or change the context of a function. Such a function
may be anything from a click-handler to an object’s method. “this” (context)
binding is very common in building web-applications, so knowing exactly
what it does will make your JavaScript skills more versatile.

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.

Let’s look at the function bind implementation from three angles:

1. The basic problem function bind solves


2. The edge-cases to consider

3. The code and the JavaScript it teaches us

First, the basic problem that bind() solves:


Function.prototype.bind & bind do the same thing. They are simply
implemented slightly differently as we will see in the third heading. Below, I
will use examples from both.

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.”

jimbot.greet() //=> 'Say hello to 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:

boundGreet = bind(jimbot.greet, { name: 'Janice' });

boundGreet() //=> 'Say hello to Janice'

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);
}
};

var boundGreet = jimbot.greet.bind(jimbot);


boundGreet(); // alerts 'Say hello to Jimbot'

boundGreet = jimbot.shout.bind({ name: 'Janice' });


boundGreet(); // alerts 'Say hello to Janice'

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 ...

Second, the edge-cases:


The example above was a simple operation. What if we need to do
something a bit more complex such as the operation below?

var func = function(a, b){ return a + b }; // method

var boundFunc = bind(func, null, 'foo'); // binding (with previous


arguments)

boundFunc('bar'); //=> 'foobar' // output (with current arguments)

1. What’s going on here? Basically, bind should be able to accept


arguments in addition to function (func) and context (null). In this
case, that additional argument is the string “foo.”

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.

Third, the code and the JS it teaches us:


Tools to use:
1. Since we can’t use native bind() for our implementation, let’s use
[].prototype.slice.call() to build our array of arguments and
Function.prototype.apply() in order to apply context to method.

2. An anonymous function declaration (may use a function expression as


well) that will be returned within our implementation. We need such an
inner function in order to capture the return value so that function bind
may be stored for later use.

Function bind outline:

let bind = function(func, context) {

return function() {

}
};

We know we want two named parameters and return an inner function.


What’s next?

let bind = function(func, context) {


let previousArgs = [].slice.call(arguments, 2);
return function() {

}
};

Assign any additional arguments that may be passed in to a variable


“previousArgs.” [].slice.call(arguments, 2) will produce an array of
arguments after the first two. We will need these arguments for the inner
function.

let bind = function(func, context) {


let previousArgs = [].slice.call(arguments, 2);

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:

let bind = function(func, context) {


let previousArgs = [].slice.call(arguments, 2);

return function() {
let currentArgs = [].slice.call(arguments);
let combinedArgs = [].concat(previousArgs, currentArgs);
return func.apply(context, combinedArgs);
}
};

The variable currentArgs is the hypothetical body of arguments that


may/will be passed in when bind() is called later. Here, we turn
currentArgs into an array, concatenated with the previousArgs; and that
combinedArgs is passed into the .apply() to be applied as func’s arguments.

A simple sample use-case of our implementation:

var func = function(a, b) {


return a + b
};

var boundFunc = bind(func, null, 'foo');


var result = boundFunc('bar');

result === 'foobar'; // true

var result = boundFunc('baz');

result === 'foobaz'; // true

Final Code:

let bind = function(func, context) {


let previousArgs = [].slice.call(arguments, 2);

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:

Closure: Calling .bind() creates a closure, which grants .bind() access to


the previousArgs. So when .bind() is saved to a variable and used later,
it still has access to the previous arguments.

this keyword: this is a powerful tool in Object-Oriented programming,


subclassing, and modularizing code. If we learn how to bind contexts
properly, we can write elegant code.

.apply() vs .call(): Both methods are identical in function but slightly


different in implementation. apply takes an array of arguments; call
takes a column-list of arguments.

JavaScript ES6 Algorithms

About Help Legal

You might also like