【问题标题】:explanation about prototype.js function binding code关于prototype.js函数绑定代码的解释
【发布时间】:2011-02-10 12:39:27
【问题描述】:

发件人: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)));

【问题讨论】:

    标签: javascript jquery prototypejs resig


    【解决方案1】:

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

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

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

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

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

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

    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
    

    【讨论】:

      【解决方案2】:

      旧帖子但新方法;)

      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 是一个本地对象,在函数调用期间自动分配。

      【讨论】:

        猜你喜欢
        • 2017-06-05
        • 2014-09-06
        • 1970-01-01
        • 1970-01-01
        • 2014-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-08
        相关资源
        最近更新 更多