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