JavaScript类变量在回调函数中的作用域

11

可能是重复问题:
在Javascript中,为什么“this”运算符不一致?

我有以下类:

function Chat(some, nick, url) {
    this.socket = null;
    this.Nickname = nick;
    this.Url = url;

    this.Connect = function () {
        socket = io.connect(this.Url);
        socket.on('connect', function (data) {
            var p = this.Nickname; //this.Nickname is undefined why? 
            // how can I acess to the Nickname variable or function?
        }
    };
}

如何从连接回调函数中访问实例变量或函数?


1
this.Connect 上面,你应该能够做 var obj = this; 然后在函数内使用该变量。 - Danny
感谢您提供的所有答案!它们都是正确的!但我只能选择一个。 - elranu
6个回答

36

最简单的解决方案是使用 that 技巧。

var that = this; //that is a normal variable
                 //so it is lexically scoped
                 //and can be used in inner functions

socket.on('connect', function(data){
    var p = that.NickName;
});

另一种可能性是将正确的this显式地绑定到回调函数

socket.on('connect', function(data){
    var p = this.Nickname;
}.bind(this));

that 的技巧之所以优越,是因为它可以嵌套到任意多个回调函数中,而 bind 版本的优点是允许你在内部继续使用 "this"。

bind 方法的缺点是它不支持 IE<=8,因此如果需要支持古老的浏览器,可能需要使用一个 shim。

编辑:这个答案有点旧了。如今,您可能不需要再担心 IE6 了,您可能能够使用箭头函数语法,它不会覆盖 this


5
关于bind()方法需要注意的是,由于你正在使用node.js(并且你了解你的Javascript引擎),你知道V8在其中实现了一些ECMAScript 5功能(https://github.com/joyent/node/wiki/ECMA-5-Mozilla-Features-Implemented-in-V8),你实际上拥有bind()函数,并且可以安全地使用它! :) - RyanWilcox

2
您可以将此代码: var p = this.Nickname; 改为 var p = nick; 您的问题在于,this 指的是您在回调函数中使用的本地作用域,而不是外部函数的作用域。

2
问题在于,在JavaScript中,this值的取值取决于回调函数的调用方式。最简单的解决方法是将原始的this对象保存到本地命名为self的变量中。该变量被回调函数捕获,可以用于访问成员值。例如:
function Chat(some, nick, url) {
    var self = this;  
    this.socket = null;
    this.Nickname = nick;
            this.Url = url;

    this.Connect = function () {
        socket = io.connect(this.Url);
        socket.on('connect', function (data) {
            var p = self.Nickname; //this.Nickname is undifined why? 
             // how can I acess to the Nickname variable or function?
        }
    };
  }

1

JavaScript有闭包,可以说它们非常巧妙。

看看这个问题:

JavaScript闭包是如何工作的?

这应该可以帮助你理解为什么每个人都建议你在函数上面放置var something = this并在其中使用something来维护对原始this的引用。


1
这是一个演示如何使用本地副本的小把戏:

http://jsfiddle.net/k7vC6/1/

在这种情况下,thisself 是同一件事,但使用 self 更安全。

1

"this" 在该作用域中代表您的函数。

尝试:

function Chat(some, nick, url) {
    this.socket = null;
    this.Nickname = nick;
        this.Url = url;

    var that = this;

    this.Connect = function () {
        socket = io.connect(this.Url);
        socket.on('connect', function (data) {
            var p = that.Nickname; //this.Nickname is undifined why? 
            // how can I acess to the Nickname variable or function?
        }
    };
}

请注意将“this”分配到“that”中。

this 真的代表了 函数 吗?我以为它代表了 调用者 - Doug Moscrop
这是一个很好的问题,你知道吗,我不确定它代表调用者还是该方法所属的对象。无论如何,你是对的,它不代表内部函数。 - u.k
@Uzi:Javascript中的this是根据函数调用方式设置的。如果你执行f(),那么this将是未定义或全局对象。如果你执行obj.f(),那么this将是obj,最后你也可以使用f.call(myThis, 1, 2)或f.apply来选择自己想要的this。函数不知道它们来自哪个“类”,而且this完全是随意的。 - hugomg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接