11

Possible Duplicate:
In Javascript, why is the “this” operator inconsistent?

I have the following class:

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?
        }
    };
}

How can I acces the instance variable or function from the connect callback function?

Community
  • 1
  • 1
elranu
  • 2,292
  • 6
  • 31
  • 55
  • 1
    Above `this.Connect` you should be able to do `var obj = this;` and then use that variable within the function. – Danny Nov 29 '11 at 21:08
  • Thanks for all your awnsers! there all correct! but I can only select one. – elranu Nov 29 '11 at 21:17

6 Answers6

36

The simplest solution is to use the that trick

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

Another possibility is explicitily binding the correct this to the callback function

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

The that trick has the advantage of nesting to as many callbacks as you want and the bind version has the advantage of allowing you to still use "this" inside.

A disadvantage of the bind method is that it is not supported in IE<=8 so you might need to use a shim if you need to support ancient browsers.

edit: This answer is a bit old. Nowadays you probably don't need to worry about IE6 anymore and you might be able to use fat arrow syntax, which doesn't overwrite the this.

hugomg
  • 68,213
  • 24
  • 160
  • 246
  • 5
    Something to note about the bind() method is that, since you're in node.js (and you know your Javascript engine) you know that V8 has some ECMAScript 5 features implemented in it (https://github.com/joyent/node/wiki/ECMA-5-Mozilla-Features-Implemented-in-V8), you actually have the bind() function and can use it safely! :) – RyanWilcox Nov 29 '11 at 22:02
2

The problem is the this value in javascript can change depending on how the callback is invoked. The easiest way to work around this is to save the original this object into a local named self. The local is captured in the callback and can be used to access member values. For example.

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?
        }
    };
  }
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
2

You can change this: var p = this.Nickname; to this var p = nick;

Your problem is that this refers to the local scope of the function you are using in the callback. It's not the scope of the outer function.

kemiller2002
  • 113,795
  • 27
  • 197
  • 251
1

"this" is representing your function in that scope.

try :

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?
        }
    };
}

Note the assignment of "this" into "that"

Doug Moscrop
  • 4,479
  • 3
  • 26
  • 46
u.k
  • 3,091
  • 1
  • 20
  • 23
  • Does `this` really represent the *function*? I thought it represented the *caller*? – Doug Moscrop Nov 29 '11 at 21:24
  • Thats a good question, you know, I am not sure if it represents the caller, or the object that this method is a member of. in any case, you are right, it does not represent the internal function. – u.k Nov 29 '11 at 21:46
  • @Uzi: Javascript this is set depending how the function was called. If you do f() the this will be undefined or the global object. If you do obj.f() this will be the obj and finally you can also use the this of your choice with f.call(myThis, 1, 2) or f.apply. Functions do *not* know what "class" they are from and the `this` is wholy promiscuous. – hugomg Nov 29 '11 at 22:00
1

JavaScript has closures which are, to say the least, nifty.

Have a look at this question:

How do JavaScript closures work?

It should help you understand why everyone is telling you to put a var something = this above the function and use something inside of it to maintain a reference to the original this.

Community
  • 1
  • 1
Doug Moscrop
  • 4,479
  • 3
  • 26
  • 46
1

Here's a fiddle that shows using the local copy of this:

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

In that instance, this and self are the same thing, but using the self is safe.

Matt H
  • 6,422
  • 2
  • 28
  • 32