Javascript原型绑定

时间:2010-07-20 21:14:56

标签: javascript prototype bind

我是基于原型的语言的新手并且已经阅读了这个问题:

Preserving a reference to "this" in JavaScript prototype functions

我想知道有什么价值,使用基于原型的签名将方法附加到对象。为什么不直接将方法附加到对象定义中的对象属性?

其次,当使用原型签名来定义对象的方法时,为什么'this'指针会解析为函数内的window对象?这似乎是一个设计缺陷。如果不是某人可以解释,或指出我为什么不解释?

谢谢。

编辑:

此代码按预期执行,呈现一个带有“here”字样的消息框。

function Obj()
{   
    this.theVar = 'here';
    this.method2 = function(){ alert( this.theVar ); }
}

Obj.prototype.method3 = function(){ this.method2(); }
Obj.prototype.method4 = function(){ this.method3(); }

var obj = new Obj();
obj.method4();

此代码是我的AJAX回调,'this'指针在执行期间引用'window'对象。

Test.prototype.nextCallback = function( response )
{
    if( response.Status != 'SUCCESS' )
        show_message( response.Message, false );
    else
        this.setQuestion( response.Question );
}

Test.prototype.setQuestion = function( question ){ ... }

'this'指针实际上在AJAX调用之前正常工作,但之后没有。这是因为在AJAX调用返回之后和调用回调之前,nextCallback()上下文没有正确恢复吗?有没有办法解决这个问题?

3 个答案:

答案 0 :(得分:1)

1-在构造函数的原型上添加成员的重点是行为重用。

从该原型继承的所有对象实例将能够通过原型链 解析成员,同样成员只定义一次,而不是在每个实例中定义

2-这是因为每个函数都有自己的执行上下文(存储this值的地方),并且在调用函数时隐式设置this值,如果是函数reference没有基础对象(例如foo();,vs obj.foo()),全局对象将设置为调用方法中的this值。

有关详细信息,请参阅this answer的第二部分。

编辑:查看代码之后,似乎您正在传递nextCallback方法的引用作为某些Ajax成功事件的回调函数,如果是这样的话,那么基础对象是引用将丢失,这是一种常见的方法,可以使用正确调用您的方法的匿名函数,例如:

var obj = new Test();
//...
someAjaxLib(url, function (data) {
  obj.nextCallback(data); // `this` will refer to obj within nextCallback
});

另一种方法可以是在构造函数中将方法绑定到其实例,请记住该方法将被定义为您创建的每个对象实例上的自己的属性,它不会被继承,例如:

function Test() {
  var instance = this; // store reference to the current instance

  this.nextCallback = function( response ) {
    if( response.Status != 'SUCCESS' ) {
      show_message( response.Message, false );
    } else {
      instance.setQuestion( response.Question ); // use the stored reference
    }
  }
}

答案 1 :(得分:0)

  1. 在JavaScript中,如果使用函数作为构造函数来创建新对象,则在构造函数中将方法分配给this意味着每个新对象都会定义一个新方法。分配给原型意味着您只能在原型中获得该方法的一个定义。

  2. 是的,this在某些情况下指向全局对象是一个设计缺陷,但我不认为在你提到这种情况的情况下会发生这种情况。

  3. 如果您想学习JavaScript对象和原型继承的最佳实践,请观看Douglas Crockford's videos

答案 2 :(得分:0)

在我的情况下,似乎当方法通过原型签名添加到对象,然后传递用作AJAX回调方法时,该方法然后重新作用于全局对象(窗口)并失去其原始背景。也就是说,该方法不再是定义它的原型的成员。

我只在Firefox中测试过这个。我猜测这种行为是因为AJAX调用是在不同的OS线程上物理执行的,并且在从AJAX调用返回时,找到并执行指定的回调方法。不尝试在线程之间解析方法的原始上下文。这只是一个猜测。