我正在阅读一本关于编写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]发布于 2017-04-17 09:09:11
这让我回想起求解和扩展方程的日子。
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代数规则,并将调用替换为调用.。
实际上,我们实施了一个替代方案,其基础是:
someFunction.bind(arg1)(arg2) <==> someFunction.call(arg1, arg2)因此,我们可以替换它并得到:
var fn = Function.prototype.bind.call(Function.prototype.bind.apply, [].concat);4 .对于我们的第二个js代数规则,我们设计了:
someFn.bind.call(target, ...) <==> target.bind(...)。
someFn在这里并不重要,因为我们不对它调用bind()。我们在bind上调用bind--替换曾经是someFn的this,并为此将其替换为target。
因此,我们将bind.call(target)替换为target.bind选项。
var fn = Function.prototype.bind.apply.bind([].concat) 5 .如果最后一次置换也在执行调用(),我们可以执行一个替换,如:
fn([1, 2], [3, 4]) <==> [].concat.apply([1, 2], [3, 4])但是,我们只有没有调用的绑定,我们可以替换该绑定,并且等效于:
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函数,并允许我们使用函数样式,而无需从对象调用它。concat没有绑定到调用方的this,而是将其作为this在arg1上应用,arg2作为连接到arg1的其他参数。
fn([1, 2], [3, [5, 6], 4])
// [1, 2, 3, 5, 6, 4]发布于 2017-04-17 09:53:49
因为Function.prototype.bind本身就是一个函数,所以它作为一个方法继承自己。
通常,bind作为特定函数的实例方法调用,但我们可以将其重新绑定到Function.prototype.apply并返回一个高阶函数。
一种不那么简洁的写作方式是:
function apply (fn) {
return function (a, b) {
return fn.apply(a, b)
}
}发布于 2017-04-17 16:59:59
我们必须考虑一下bind在幕后实际做了什么。粗略地说,它的工作方式如下:
function bind(fn, ...bound) {
return (...other) => this.call(fn, ...bound, ...other);
}(请记住,词法this引用了调用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);我们现在可以在[].concat上调用[].concat
fn = (obj, args) => [].concat.apply(obj, args);obj需要是一个数组才能工作,因此这简化为:
fn = (obj, args) => obj.concat(...args);在提供的示例中,我们以
[1, 2, 3].concat(4, [5, 6], 7)返回预期的结果。
https://stackoverflow.com/questions/43446378
复制相似问题