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
调用 – replacethis
是someFn
,因此它被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
因为this
和arg2
作为其他参数连接到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);