代码之家  ›  专栏  ›  技术社区  ›  resopollution

prototype.js函数绑定代码说明

  •  1
  • resopollution  · 技术社区  · 16 年前

    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)));
      };
    };
    

    另外,有人能解释为什么args.concat是必要的吗?为什么不重新写为:

    fn.apply(object, args)
    

    return fn.apply(object,
              args.concat(Array.prototype.slice.call(arguments)));
    
    2 回复  |  直到 14 年前
        1
  •  7
  •   Anurag    16 年前

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

    你可能已经知道这一点了,但说起来也没什么坏处。如果我们不包装 fn.apply 在另一个函数中,则直接调用该函数 fn 这是次优的,就像 bind 只应该设置执行上下文(应该 this 在函数中引用),而不是调用它。

    Javascript方法可以通过调用 call apply 他们的方法。下面是一个小例子:

    function example() {
        alert("useless example");
    }
    
    example.apply() // or example.call(), alerts "useless example";
    

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

    在fn.apply中执行args.concat的原因是不同的,它不是可选的。 绑定

    args 表示调用时传递的参数 绑定 关于函数。 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
    
        2
  •  0
  •   F4b    10 年前

    旧的职位,但一个新的方法;)

    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)))
    

    使用一个特殊参数对象={0:4,1:5,2:6},可以使用[].slice.call将其转换为数组 其中参数是一个本地对象,在函数调用期间自动赋值。