javascript - nodejs - 'this' yang mana ini?


Jadi ini pertanyaan yang canggung untuk ditanyakan, tapi saya sedang belajar NodeJS dan saya punya pertanyaan. Di Java, ketika saya memanggil metode dari sebuah objek, instance this tetap sama (seperti pada contoh ini).

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

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

Ini mengembalikan true (secara teori, itu kode dari ingatan saya). Namun, di NodeJS ketika saya mencoba melakukan sesuatu yang serupa, itu gagal.

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

Pertanyaan saya adalah mengapa ini bisa terjadi, dan jika ini dilakukan secara salah oleh saya, bagaimana saya dapat merujuk dengan benar ke variabel lain dalam instance MyObject dari metode onError?

Jawaban #1

Di JavaScript, "metode" hanyalah fungsi yang merupakan bagian dari sebuah objek.

Jika kamu melakukannya

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

The this di onError akan menjadi objek obj (karena itu adalah objek dari mana ia dipanggil)

Sebaliknya, dalam kasus Anda, Anda melewatkan this.onError ke EventEmitter, itu akan memanggil fungsi itu dengan EventEmitter (OtherObject) sebagai this.

Untuk menghindari masalah itu, gunakan fungsi anonim.

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

Dengan cara ini Anda mengikatnya kembali ke objek yang Anda harapkan

Jawaban #2

Ada cara yang lebih sederhana - Anda bisa menggunakan fungsi 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