【问题标题】:JavaScript prototype bindJavaScript 原型绑定
【发布时间】:2010-07-20 21:14:55
【问题描述】:

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

Preserving a reference to "this" in JavaScript prototype functions

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

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

谢谢。

编辑:

此代码按预期执行,呈现一个消息框,其中包含单词“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() 上下文吗?有没有办法解决这个问题?

【问题讨论】:

  • 我不认为你的意思是“原型签名”——你说的是原型属性,不是吗?
  • “原型签名”是指定义这样的方法:myObj.prototype.myFunction = function(){ ... }

标签: javascript prototype bind


【解决方案1】:

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

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

2- 发生这种情况是因为每个函数都有自己的执行上下文(这是存储 this 值的位置),并且在调用函数时会隐式设置 this 值,并且如果函数引用没有 基础对象(例如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
    }
  }
}

【讨论】:

  • 感谢您回复 CMS。您似乎对该主题有深入的了解,我想发布更多代码,向您展示我正在尝试完成的工作。我将在下面发布一个答案,以便更具可读性。
  • 我同意。请参阅下面的答案。
【解决方案2】:
  1. 在 JavaScript 中,如果您使用函数作为构造函数来创建新对象,那么在构造函数中将方法分配给 this 意味着每个新对象都定义了一个新方法。分配给原型意味着您只能在原型中获得一个方法定义。

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

如果您想了解 JavaScript 对象和原型继承方面的最佳实践,请观看Douglas Crockford's videos

【讨论】:

  • 谢谢 Skilldrick,我一定会看看这些视频。
【解决方案3】:

在我的例子中,当该方法通过原型签名添加到对象,并随后作为 AJAX 回调方法传递时,该方法将重新作用于全局对象(窗口)并丢失其原始语境。也就是说,该方法不再是定义它的原型的成员。

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

【讨论】:

  • 它与方法如何被调用有关,因为你只传递一个对它的引用,Ajax 库通常会调用一个参数,没有任何基础对象信息,例如:var t = new Test(), m = t.nextCallback; m(); 在前面的例子m 指的是方法,就像如果你将它作为参数传递一样,调用m(); 会将this 的值设置为全局对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 2016-06-17
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
相关资源
最近更新 更多