Javascript绑定实现?

时间:2014-02-28 18:45:12

标签: javascript bind

由于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*/       };

但我不明白我们为什么需要arguments#9

我的意思是:

如果我有这个对象:

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....) //<----- ??

我错过了什么吗?

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

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:4)

.bind也可用作partial application解决方案。事件处理程序可能是最好的例子:

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

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

如果不传递来自实际函数调用的参数,则无法访问事件对象。