JavaScript的Bind实现?

12

由于 bind 函数不是一个跨浏览器(旧版本)的函数,因此需要使用它的 polyfill:(来自 John Resig 的书籍

/*1*/       Function.prototype.bind = function ()
/*2*/       {
/*3*/           var fn = this,
/*4*/               args = Array.prototype.slice.call(arguments),
/*5*/               object = args.shift();
/*6*/           return function ()
/*7*/           {
/*8*/               return fn.apply(object,
/*9*/                   args.concat(Array.prototype.slice.call(arguments)));
/*10*/           };
/*11*/       };

但我不明白为什么在第 #9 行需要使用 arguments

我的意思是:

如果我有这个对象:

var foo = {
    x: 3
}

我有这个函数:

var bar = function(p,b){

    console.log(this.x+'        '+p+'   '+b);
}

所以,如果我想让barfoo上下文中运行,带有参数 - 我需要做的就是:

 var boundFunc = bar.bind(foo,1,2)
 boundFunc ()...

当我运行var.bind(foo,1,2)时,arguments[object Object],1,2

这些参数保存在第4行。

很好。

现在,bind函数返回其自身的封闭函数:

function ()
    {
        return fn.apply(object,
            args.concat(Array.prototype.slice.call(arguments)));
    } 

问题

为什么我们需要在这里使用 arguments?似乎他们是用于像这样的某些东西:

var boundFunc = bar.bind(foo,1,2)
boundFunc (more1,more2....) //<----- ??

我有什么疏漏吗?

当我设置第一个var boundFunc = bar.bind(foo,1,2)时,我已经声明了参数。为什么我们需要再次声明它们?

2个回答

13

你可以在绑定函数时传递两个参数:

1) 当你调用bind函数时(第一个arguments),这些参数将始终应用于调用绑定函数时。

2) 当你调用绑定函数时(第二个arguments),这些参数是你提到的“more1,more2”。这些参数会随着绑定函数被调用时所提供的内容而改变。

第9行代码将原始的绑定函数参数与提供的额外参数结合起来。

我想你可能会对这个概念感到困惑:你不必一开始就绑定所有参数 - 你可以只绑定上下文对象,或者只绑定第一个参数,但是让调用绑定函数的人提供其余的参数。例如:

function sum() {
 var _sum = 0
 for (var i = 0; i < arguments.length ; i++) {
     _sum += arguments[i];
 }
 return _sum;
}
var sum_plus_two = sum.bind({},2);
sum_plus_two(5,7) == 14;

4

.bind 还可以作为部分应用的解决方案。事件处理程序可能是最好的例子:

var handler = function(data, event) { };

element.addEventListener('click', handler.bind(null, someData));

如果实际函数调用中的参数无法传递,您将无法访问事件对象。


事件是第一个参数,我个人认为。 - Royi Namir
但是我们已经将一个值绑定为第一个参数(someData)。因此,当事件处理程序被调用并传递事件对象时,绑定的函数将作为第二个参数接收它。如果您还没有阅读过部分应用程序文章,请阅读它,它应该会使事情更加清晰。 - Felix Kling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接