Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does `bind.bind` mean? A strange way to use JavaScript bind

Tags:

javascript

I'm reading a book about writing JavaScript frameworks and found this code snippet. But I don't understand how it works, especially the bind.bind usage? Does anyone have a clue?

var bind = Function.prototype.bind; var apply = bind.bind(bind.apply); var fn = apply([].concat); var a = [1, 2, 3], b = [4, [5, 6], 7]; fn(a, b); //output [1, 2, 3, 4, 5, 6, 7] 
like image 888
Shawn Chen Avatar asked Apr 17 '17 06:04

Shawn Chen


People also ask

What does bind mean in JavaScript?

bind is a method on the prototype of all functions in JavaScript. It allows you to create a new function from an existing function, change the new function's this context, and provide any arguments you want the new function to be called with.

Should you use BIND in JavaScript?

. bind() is used when you need to pass a callback (e.g. some sort of function reference), but you want the caller to call your function with a specific this value.

What does bind this mean?

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

What is bind and apply in JavaScript?

Apply invokes the function and allows you to pass in arguments as an array. Bind returns a new function, allowing you to pass in a this array and any number of arguments.


1 Answers

This takes me back to the days of solving and expanding equations.

1 . First, lets expand the first apply function:

var bind = Function.prototype.bind; var apply = bind.bind(bind.apply); var fn = apply([].concat); 

Transforms to:

var apply = Function.prototype.bind.bind(Function.prototype.bind.apply); var fn = apply([].concat) 

2 . Secondly, we expand the fn function:

var fn = Function.prototype.bind.bind(Function.prototype.bind.apply)([].concat); 

3 . We now invent a js algebra rule and replace the bind.bind...() invocation with the call invocation.

Actually we implement a replacement base on the notion that:

someFunction.bind(arg1)(arg2) <==> someFunction.call(arg1, arg2) 

Therefore we can replace that and get:

var fn = Function.prototype.bind.call(Function.prototype.bind.apply, [].concat); 

4 . For our second js algebra rule we devise that:

someFn.bind.call(target, ...) <==> target.bind(...).

someFn is not important here because we don't call bind() on it. We invoke call on the bind - replacing the this that was someFn and therefor it is replaced with target.

Therefore we replace the bind.call(target) with the target.bind alternative

var fn = Function.prototype.bind.apply.bind([].concat)  

5 . If the last permutation was also doing invocation () we could have done a replace like:

fn([1, 2], [3, 4]) <==> [].concat.apply([1, 2], [3, 4]) 

But we have only the bind without the invocation which we can replace and is equivalent to:

var fn = function (arg1, arg2) {      return [].concat.apply(arg1, arg2);  } // instead arg1 and arg2 we could use more accurate arguments logic also. 

Final Result

var fn = Function.prototype.bind.apply.bind([].concat)   // or  var fn = function (arg1, arg2) {      return [].concat.apply(arg1, arg2);  } 

The fn function takes the concat function and lets us us it in a functional style, without calling it from an object. Instead of concat binded to this of the caller, fn applies it on arg1 as this and arg2 as the other params to concatenation to arg1.

fn([1, 2], [3, [5, 6], 4]) // [1, 2, 3, 5, 6, 4] 
like image 135
elpddev Avatar answered Oct 05 '22 16:10

elpddev