2015-07-02 15 views
6

Quindi questa è una domanda scomoda da chiedere, ma sto imparando NodeJS e ho una domanda. In Java quando chiamo un metodo da un oggetto, l'istanza this rimane la stessa (come in questo esempio).nodejs - Quale "questo" è questo?

private Test inst; 
public Test() { 
    inst = this; 
    this.myFunction(); 
} 

private void myFunction() { 
    System.out.println(inst == this); 
} 

Questo restituisce vero (in teoria, questo è il codice dalla cima della mia testa). Tuttavia, in NodeJS quando tento di fare qualcosa di simile fallisce.

var MyObject = function() { 
    this.other = new OtherObject(); 
    this.other.on("error", this.onError); 
    console.log(this); //This returns the MyObject object 
} 

MyObject.prototype.onError = function (e) { 
    console.log(this); //This returns the OtherObject object, where I thought it would return the MyObject object. 
} 

La mia domanda è perché è così, e se questo è stato fatto in modo non corretto da parte mia, come posso correttamente riferimento altre variabili nell'istanza MyObject dal metodo onError?

+0

per quanto ne so, 'this' in JavaScript è molto difficile. In caso di chiamata in funzione, punta al chiamante, non all'oggetto in cui è definita la funzione. – walther

+1

@ walther- * questo * in javascript non è affatto complicato. È impostato dalla chiamata o dall'uso di * bind *, il gioco è fatto. Anche se è diverso dalle altre lingue, non è molto difficile da capire. – RobG

+0

@RobG, questa è proprio la parte difficile: altri linguaggi lo fanno in modo diverso e confonde l'inferno di alcuni sviluppatori. Se fosse davvero chiaro, una domanda come questa non si presenterebbe mai (e questo non è il primo, né l'ultima volta). – walther

risposta

6

In JavaScript i "metodi" sono solo funzioni che fanno parte di un oggetto.

Se fai

var obj = new MyObject(); 
obj.onError(); 

Il questo onError sarà l'oggetto obj (perché è l'oggetto che viene richiamato da)

Invece in voi caso in cui si sta passando alla this.onError EventEmitter chiamerà quella funzione con EventEmitter (OtherObject) come questo.

Per evitare questo problema, utilizzare una funzione anonima.

var MyObject = function() { 
    var self = this; 
    this.other = new OtherObject(); 
    this.other.on("error", function (e) { self.onError(e); }); 
} 

In questo modo si sono vincolanti questo torna a l'oggetto che si aspettano

+1

Grazie per aver spiegato questo così bene e per l'ottimo esempio di utilizzo! – duper51

+1

Per una soluzione ancora più pulita utilizzare il metodo bind https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind – B3rn475

+0

@RobG era un sistema di sicurezza. A proposito risolto – B3rn475

0

Non c'è modo più semplice - è possibile utilizzare la funzione bind.

var EventEmitter = require('events').EventEmitter; 

var MyObject = function() { 
    this.other = new EventEmitter(); 
    this.other.on("error", this.onError.bind(this)); 
    console.log(1, this instanceof MyObject); // 1, true 
}; 

MyObject.prototype.onError = function (e) { 
    console.log(2, this instanceof MyObject); // 2, true 
}; 

MyObject.prototype.callError = function (e) { 
    console.log(3, this instanceof MyObject); // 3, true 
    this.other.emit('error', e); 
}; 

var mo = new MyObject(); 

mo.callError(new Error(1)); 

Demo