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]
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.
. 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.
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.
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.
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With