1

来自:http ://ejohn.org/apps/learn/#2

Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

谁能告诉我为什么需要第二次退货(在 fn.apply 之前)?

另外,谁能解释为什么 args.concat 是必要的?为什么不将其重写为:

fn.apply(object, args)

代替

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

2 回答 2

7

第二次返回是必要的,否则我们将丢失绑定函数的任何返回值。

您可能已经知道这一点,但不要提及。如果我们不包装fn.apply在另一个函数中,那么我们将直接调用fn次优函数,因为bind它只应该设置执行上下文(应该this在函数内部引用的内容),而不是调用它。

Javascript 方法可以通过调用它们的callorapply方法来调用。这是一个小例子:

function example() {
    alert("useless example");
}

example.apply() // or example.call(), alerts "useless example";

Prototype 的 bind() 中的外部函数应该像绑定函数的不可见包装器一样工作。因此,传递给包装器的任何参数也应该传递给绑定函数,并且它必须返回绑定函数返回的任何值,这就是 return 语句存在的原因。

在 fn.apply 中执行 args.concat 的原因是不同的,它不是可选的。bindin Prototype 允许您将参数添加到绑定函数。

args表示我们调用bind函数时传递的参数。arguments表示当我们调用绑定函数时传递的参数。我们基本上在那里连接两个数组。

从上面的例子:

var obj = { x: 'prop x' };
var boundExample = example.bind(obj, 12, 23); // args => 12, 23
boundExample(36, 49); // arguments => 36, 49

// arguments that our example() function receives => 12, 23, 36, 49
于 2010-04-21T10:51:55.563 回答
0

旧帖子,但新方法;)

Function.prototype.bind = function(){
    var fn = this, 
    context = arguments[0], 
    args = Array.prototype.slice.call(arguments, 1);
    return function(){
        return fn.apply(context, args.concat([].slice.call(arguments)));
    }
}

obj = {'abc':'x'};
var func = function() {
  console.log(arguments);
  alert(this.abc);
}
var x = func.bind(obj);

console.log(x(1,2,3));

这是一个很好的例子来解释。运行它并检查控制台日志。然后修改代码省略

[].slice.call(arguments)

您将看到执行 x(1,2,3) 的 console.log 不再显示参数。这是因为 arguments 对象是所有函数中的局部变量。 这听起来可能有点令人困惑,但它的意思基本上是:

var x = func.bind(obj,1,2,3);

在内部返回此函数:

function() {
    return fn.apply(obj, [1,2,3].concat([].slice.call(arguments)));
}

所以它更像是函数的模板。

当你现在运行它时:

x(4,5,6)

这将运行:

fn.apply(obj, [1,2,3].concat([].slice.call(arguments)))

带有特殊参数 object = {0:4,1:5,2:6} ,可以使用 [].slice.call 将其转换为数组,其中 arguments 是本地对象,在调用期间自动分配功能。

于 2015-05-25T13:45:21.127 回答