使用Bind强调行为

时间:2011-04-09 05:43:56

标签: javascript underscore.js

通过以下方式阅读来源: http://documentcloud.github.com/underscore/underscore.js

这是经常使用的_bind方法(为清晰起见,我删除了本机检查)

   _.bind = function(func, obj) {
    var args = slice.call(arguments, 2);
    return function() {
      return func.apply(obj, args.concat(slice.call(arguments)));
    };
  };

通过func.apply传递的args似乎在最后不必要地重复了

使用节点解释器的示例(删除最后一行以在Firebug等中尝试..)

var arguments = [1,2,3,4,5,6];
var args = Array.prototype.slice.call(arguments, 2);
var appliedArgs = args.concat(Array.prototype.slice.call(arguments));
require('sys').puts(appliedArgs);

输出:

3,4,5,6,1,2,3,4,5,6

我非常怀疑我发现了一个错误,但是为什么它以这种方式工作很困惑,为什么再次以这种方式附加args。混淆

2 个答案:

答案 0 :(得分:16)

bind方法返回一个闭包,它可以接受要传递给函数的其他参数。下划线代码中对arguments的两个引用不引用同一组参数。第一个来自封闭函数,第二个来自返回的闭包。以下是此方法的略微修改版本,希望更清楚:

_.bind = function(func, obj /*, arg1, arg2 ... argN */) {

  // Prepare default arguments for currying, removing
  // the function and object references
  var args = Array.prototype.slice.call(arguments, 2);

  // Return a closure that has access to the parent scope
  return function(/* arg1, arg2 ... argN */) {

    // Prepare arguments that are passed when bound
    // method is called
    var args2 = Array.prototype.slice.call(arguments);

    // Curry the method with the arguments passed
    // to the enclosing function and those passed
    // to the bound method
    return func.apply(obj, args.concat(args2));

  }

这实际上允许您在方法绑定到对象时对其进行curry。其用法的一个例子是:

var myObj = {},
    myFunc = function() {
      return Array.prototype.slice.call(arguments);
    };

myObj.newFunc = _.bind(myFunc, myObj, 1, 2, 3);

>>> myObj.newFunc(4, 5, 6);
[1, 2, 3, 4, 5, 6]

答案 1 :(得分:1)

_bind的调用将对象和方法的某些参数绑定在一起。您可以在调用绑定方法时将其他参数传递给绑定方法。你不可能两次传递相同的参数。用法是:

function sum() {
    var total = 0;
    for (var i=0; i < arguments.length; ++i) {
        total += arguments[i];
    }
    return total;
}
var sumsome = _bind(sum, {}, 1, 2, 3);
sumsome(4,5,6); // equivalent to the call ({summ: sum}).summ(1,2,3,4,5,6)
sumsome('a','b','c'); // equivalent to the call ({summ: sum}).summ(1,2,3,'a','b','c')