bind.bind是什么意思? 一个奇怪的方式来使用JavaScript绑定

我正在阅读一本关于编写JavaScript框架的书,并发现了这个代码片段。 但我不明白它是如何工作的,特别是bind.bind用法? 有人有线索吗?

 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] 

这使我回到了求解和扩展方程式的日子。

1。 首先,让我们展开第一个应用函数:

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

转换为:

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

2。 其次,我们扩展fn函数:

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

3。 我们现在发明了一个js代数规则,并用调用调用来replacebind.bind...()调用。

其实我们实行替代基础的概念是:

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

因此,我们可以取代,并得到:

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

4。 对于我们的第二个js代数规则,我们devise:

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

someFn在这里并不重要,因为我们不调用bind()。 我们调用bind调用 – replacethissomeFn ,因此它被replace为target

因此我们用bind.call(target)replacebind.call(target)

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

5。 如果最后的排列也在调用(),我们可以做一个replace,如:

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

但是我们只有没有我们可以replace的调用的约束,相当于:

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

最后结果

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

fn函数接受concat函数,让我们以函数forms使用它,而不用从对象中调用它。 而不是concat绑定到this调用者, fn将它应用于arg1因为thisarg2作为其他参数连接到arg1

 fn([1, 2], [3, [5, 6], 4]) // [1, 2, 3, 5, 6, 4] 

因为Function.prototype.bind本身就是一个函数,所以它inheritance自己作为一个方法。

通常,绑定被称为特定函数的实例方法,但是我们可以将其重新绑定到Function.prototype.apply并返回一个更高阶的函数。

一个不太简洁的写作方式是:

 function apply (fn) { return function (a, b) { return fn.apply(a, b) } } 

我们必须考虑一下幕后实际bind的内容。 粗略地说,它是这样工作的:

 function bind(fn, ...bound) { return (...other) => this.call(fn, ...bound, ...other); } 

(请记住,这个词是指bind被调用的函数)

 apply = bind.bind(bind.apply); 

并手动展开bind自己,我们得到:

 apply = (...other) => bind.call(bind.apply, ...other); 

我们只关心传递一个参数,这是一个函数。 希望这也意味着它的apply性能与bind的相同:

 apply = (fn) => bind.call(fn.apply, fn); 

但是bind (希望)本身也是fn.apply的原型,所以我们可以进一步简化为:

 apply = (fn) => fn.apply.bind(fn); 

我们现在可以再次扩大bind

 apply = (fn) => (...other) => fn.apply.call(fn, ...other); 

这一次,我们需要两个参数,呼叫的call也可以简化:

 apply = (fn) => (obj, args) => fn.apply(obj, args); 

我们现在apply[].concat上调用apply

 fn = (obj, args) => [].concat.apply(obj, args); 

obj需要成为一个数组才能工作,所以这简化为:

 fn = (obj, args) => obj.concat(...args); 

在提供的例子中,我们结束了

 [1, 2, 3].concat(4, [5, 6], 7) 

这将返回预期的结果。

bind()方法将该函数的新实例创build为传递给bind()

这里我们调用Function.prototype.bind.apply(Function.prototype, [null].concat(arguments)); 通过分解成单独的可执行代码单元。

目标是打电话apply ; 作为第一个parameter passing原始函数,然后传递参数数组。

这个代码对于每一个涉及到dynamic参数绑定的进程都有不同的variables。

 var bind=Function.prototype.bind; // the bind function is assigned to a var var apply=bind.bind(bind.apply); // a new function apply is created which is nothing but bind.apply var fn=apply([].concat); // the apply function is defined and now we have final function that will concat array. 

最后两行是通过传递两个参数来执行fn函数

var a=[1,2,3],b=[4,[5,6],7]; fn(a,b);