2011-11-29 8 views
6

Duplicar posibles:
In Javascript, why is the “this” operator inconsistent?Javascript clase de alcance variable en función de devolución de llamada

que tienen la clase siguiente:

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

Cómo puedo acces la variable de instancia o función desde la función de devolución de llamada?

+1

Sobre 'this.Connect' deberías poder hacer' var obj = this; 'y luego usar esa variable dentro de la función. – Danny

+0

¡Gracias por todas tus felicitaciones! ¡Todos correctos! pero solo puedo seleccionar uno. – elranu

Respuesta

26

La solución más sencilla es utilizar el that truco

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

Otra posibilidad es explicitily vinculante para la correcta esto a la función de devolución de llamada

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

El truco that tiene la ventaja de anidación a tanto las devoluciones de llamada que desee y la versión de enlace tiene la ventaja de permitirle seguir usando "esto" dentro.

Una desventaja del método de vinculación es que no es compatible con IE < = 8, por lo que es posible que necesite utilizar una corrección si necesita admitir buscadores antiguos.

corregir: Esta respuesta es un poco viejo. Hoy en día probablemente ya no tenga que preocuparse por IE6 y pueda usar fat arrow syntax, que no sobrescribe el this.

+4

Algo a tener en cuenta sobre el método bind() es que, dado que está en node.js (y conoce su motor de Javascript), sabe que V8 tiene algunas características de ECMAScript 5 implementadas en él (https://github.com/ joyent/node/wiki/ECMA-5-Mozilla-Features-Implemented-in-V8), en realidad tiene la función bind() y puede usarla de forma segura. :) – RyanWilcox

2

El problema es que el valor this en javascript puede cambiar dependiendo de cómo se invoque la devolución de llamada. La forma más fácil de evitar esto es guardar el objeto original this en un local llamado self. El local se captura en la devolución de llamada y se puede usar para acceder a los valores de los miembros. Por ejemplo.

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

Puede cambiar esto: var p = this.Nickname; a este var p = nick;

Su problema es que this se refiere al ámbito local de la función que está utilizando en la devolución de llamada. No es el alcance de la función externa.

1

"this" representa su función en ese ámbito.

intento:

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

Nota la asignación de "este" en "que"

+0

¿Representa 'this' realmente la * función *? Pensé que representaba a * la persona que llama *? –

+0

Esa es una buena pregunta, ya sabes, no estoy seguro de si representa a la persona que llama, o el objeto al que pertenece este método. en cualquier caso, tienes razón, no representa la función interna. –

+0

@Uzi: Javascript esto se configura dependiendo de cómo se llamó la función. Si haces f(), esto será indefinido o el objeto global. Si haces obj.f() este será el obj y finalmente también puedes usar el que elijas con f.call (myThis, 1, 2) o f.apply. Las funciones no * saben de qué "clase" son y el 'esto 'es totalmente promiscuo. – hugomg

1

Javascript cierres que son, por decir lo menos, hábil.

Tener un vistazo a esta pregunta:

How do JavaScript closures work?

Debe ayudar a entender por qué todo el mundo le está diciendo a poner un var something = this por encima de la función y el uso de something dentro de ella para mantener una referencia al original this.

1

Aquí es un violín que muestra el uso de la copia local de este:

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

En ese caso, this y self son la misma cosa, pero utilizando el self es seguro.

Cuestiones relacionadas