JavaScript 原型绑定

发布于 2024-09-11 01:13:03 字数 1140 浏览 5 评论 0原文

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

在 JavaScript 原型函数中保留对“this”的引用

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

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

谢谢。

编辑:

此代码按预期执行,呈现一个消息框,其中包含“此处”一词。

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 调用之后就不行了。这个结果是因为在 AJAX 调用返回之后、调用回调之前没有正确恢复 nextCallback() 上下文吗?有办法解决这个问题吗?

I'm new to prototype-based languages and have read this question:

Preserving a reference to "this" in JavaScript prototype functions

I'm wondering what value there is, of using a prototype based signature to attach methods to an object. Why not just attach the method to the object's property in the object's definition?

Second, when using the prototype signature to define methods on an object, why does the 'this' pointer resolve to the window object inside the function? This appears to be a design flaw. If it's not could someone explain, or point me to an explanation regarding why not?

Thank you.

Edit:

This code performs as expected, rendering a message box with the word 'here' inside.

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

This code is my AJAX callback, and the 'this' pointer refers to the 'window' object during execution.

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

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

The 'this' pointer actually works properly before the AJAX call, but not after. Is this result because the nextCallback() context is not properly restored after the AJAX call returns and before the callback is called? Is there a way to remedy this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泪痕残 2024-09-18 01:13:04
  1. 在 JavaScript 中,如果您使用函数作为构造函数来创建新对象,那么在构造函数中为 this 分配一个方法意味着每个新对象都会定义一个新方法。分配给原型意味着您只能在原型中获得方法的一个定义。

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

如果您想了解 JavaScript 对象和原型继承的最佳实践,请观看 Douglas Crockford 的视频

  1. In JavaScript, if you use a function as a constructor, to create new objects, then assigning a method to this in the constructor means that each new object gets a new method defined. Assigning to the prototype means that you only get one definition of the method, in the prototype.

  2. Yes, this pointing to the global object in some cases is a design flaw, but I didn't think that in the case you mention this happens.

If you want to learn best practices in JavaScript objects and prototypal inheritance, watch Douglas Crockford's videos.

七分※倦醒 2024-09-18 01:13:04

在我的例子中,当该方法通过原型签名添加到一个对象,并随后作为 AJAX 回调方法使用时,该方法将被重新限定为全局对象(窗口)并失去其原始上下文。也就是说,该方法不再是定义它的原型的成员。

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

In my case it appears that when the method is added to an object via a prototype signature, and subsequently passed for use as an AJAX callback method, that method is then re-scoped to the global object (window) and loses its original context. That is to say, the method is no longer a member of the prototype on which it was defined.

I've only tested this in Firefox. I'm guessing this behavior is because the AJAX call is physically executed on a different OS thread, and upon return from the AJAX call the specified callback method is found and executed. No attempt is made to resolve the original context of the method between threads. Again this is just a guess.

痴梦一场 2024-09-18 01:13:03

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

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

2- 发生这种情况是因为每个函数都有自己的执行上下文(即存储 this 值的位置),并且在调用函数时会隐式设置 this 值,并且如果函数引用没有基对象(例如foo();,vs obj.foo()),则全局对象将设置为被调用方法内的 this 值。

请参阅 此答案了解更多详细信息。

编辑:查看代码后,似乎您正在传递 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- The point of adding members on a constructor's prototype, is behavior reuse.

All object instances that inherit from that prototype, will be able to resolve the member through the prototype chain, also the members are defined only once, not in every instance.

2- This happens because each function has its own execution context (that's where the this value is stored), and the this value is implicitly set when you invoke a function, and if a function reference has no base object (e.g. foo();, vs obj.foo()), the global object will set as the this value inside the invoked method.

See the second part of this answer for more details.

Edit: After looking your code, seems that you are passing a reference of the nextCallback method as the callback function of some Ajax success event, if it's so, the base object of the reference will be lost, a common approach that can be to use an anonymous function that invokes correctly your method, for example:

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

Another approach can be to bind a method to its instance within the constructor, keep in mind that the method will be defined as an own property on each object instance you create, it will not be inherited, for example:

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
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文