javascript - nodejs - Hvilken "this" er dette?


Så dette er et pinlig spørsmål å stille, men jeg lærer NodeJS og jeg har et spørsmål. I Java, når jeg kaller en metode fra et objekt, forblir this-instansen den samme (som i dette eksemplet).

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

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

Dette returnerer sant (i teorien, det er kode fra toppen av hodet mitt). Imidlertid, i NodeJS, når jeg prøver å gjøre noe lignende, mislykkes det.

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.
}

Mitt spørsmål er hvorfor dette er slik, og hvis dette blir gjort feil fra min side, hvordan kan jeg korrekt referere til andre variabler i MyObject-instansen fra onError-metoden?

Svar #1

I JavaScript er "metoder" bare funksjoner som er en del av et objekt.

Hvis du gjør

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

Dette i onError vil være obj-objektet (fordi det er objektet det kalles fra)

I stedet i ditt tilfelle sender du this.onError til EventEmitter, det vil kalle den funksjonen med EventEmitter (OtherObject) som this.

For å unngå det problemet, bruk en anonym funksjon.

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

På denne måten binder du dette tilbake til objektet du forventer

Svar #2

Det finnes en enklere måte - du kan bruke bind-funksjonen.

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