mozilla的绑定函数问题

时间:2011-04-25 00:05:29

标签: javascript

有一个关于我在Mozilla网站上找到的bind函数实现的问题。在大多数情况下,这对我来说很有意义,但我无法弄清楚这项检查的目的是什么......

this instanceof nop ? this : ( obj || {} ) 

在bind函数中。显然它检查'this'是否为空函数,但为什么需要绑定空函数。我在firebug中试过它,它有效,但重点是什么?只是想增加我的javascript知识,所以任何帮助将不胜感激。

if ( !Function.prototype.bind ) {

  Function.prototype.bind = function( obj ) {

    var slice = [].slice,
    args = slice.call(arguments, 1), 
    self = this, 
    nop = function () {}, 
    bound = function () {
      return self.apply( this instanceof nop ? this : ( obj || {} ), 
                          args.concat( slice.call(arguments) ) );    
    };

    nop.prototype = self.prototype;

    bound.prototype = new nop();

    return bound;
  };
}

2 个答案:

答案 0 :(得分:28)

它允许您将绑定函数作为构造函数调用,而不必绑定到原始对象。换句话说,如果用new调用它,“绑定”功能仍然可以像原始的未绑定版本一样工作。

以下是一个例子:

var obj = {};

function foo(x) {
    this.answer = x;
}
var bar = foo.bind(obj);   // "always" use obj for "this"

bar(42);
console.log(obj.answer);   // 42

var other = new bar(1);    // Call bar as a constructor
console.log(obj.answer);   // Still 42
console.log(other.answer); // 1

如何运作

为简化说明,这里是代码的简化版本,它只绑定this并且不处理参数或缺少obj参数:

Function.prototype.bind = function( obj ) {
  var self = this,
  nop = function () {},
  bound = function () {
    return self.apply( this instanceof nop ? this : obj, arguments );
  };

  nop.prototype = self.prototype;
  bound.prototype = new nop();

  return bound;
};

Function.prototype.bind返回的函数的行为会有所不同,具体取决于您是将其用作函数还是构造函数(请参阅ECMAScript 5语言规范的Section 15.3.4.5.115.3.4.5.2)。主要区别在于,当它被称为构造函数时,它会忽略“bound this”参数(因为在构造函数中,this需要是新创建的对象)。因此bound函数需要一种方法来确定它的调用方式。例如,bound(123)new bound(123)相对应,并相应地设置this

这就是nop函数的用武之地。它基本上充当了一个中间“类”,以便bound扩展nop扩展self(这是函数{ {1}}被召唤)。那部分是在这里设置的:

bind()

调用bound函数时,它返回以下表达式:

nop.prototype = self.prototype;
bound.prototype = new nop();

self.apply( this instanceof nop ? this : obj, arguments ) ) 通过跟踪原型链来确定this instanceof nop的原型是否等于this。通过设置nop.prototypenop.prototype = self.prototype,将使用bound.prototype = new nop()通过new bound()的原始原型创建使用self创建的任何对象。所以在函数调用中,bound.prototype(即Object.getPrototypeOf(nop)== nop.prototype)是this instanceof nop并且trueself调用(新创建的对象) )。

在正常的函数调用中,'bound()'(没有this),new将为false,因此this instanceof nop将作为obj上下文传递,是你对绑定函数的期望。

使用中间函数的原因是为了避免调用可能有副作用的原始函数(在行this中)。

答案 1 :(得分:0)

我认为这是(typeof obj != "undefined") ? obj : {}

的简短表示法

也就是说,如果未定义obj,则返回obj,否则返回一个空对象({}是一个空对象)。