處理 Callback method 中存取 class members 的常見基礎問題.
先說解決方法: 使用 arrow function, 把 callback method 的 this 與呼叫的 this 綁起來.
class MyClass{
initUI(){
let button = document.createElement('button');
button.innerHTML = 'ok';
const that = this;
button.addEventListener('click', => () {
// this.constructor.name => MyClass
console.log('this.constructor.name = ', this.constructor.name);
this.myFun(); // <--- OK
});
}
myFun(){
console.log('myFun()');
}
} // end of class
Enjoy!
by Jing.
細節:
主要是因為一個按鈕的 addEventListener 參數可以是物件也可以是一個 javascript method. 物件可以容易理解, 但如果呼叫的是 method, 那這個 method 裡面的 this reference 確定不是你原來的物件.
出問題的程式碼
class MyClass{
initUI(){
let button = document.createElement('button');
button.innerHTML = 'ok';
button.addEventListener('click', function () {
// this => HTMLButtonElement
console.log('this.constructor.name = ', this.constructor.name);
this.myFun(); // <--- Error: undefined
} );
}
myFun(){
console.log('myFun()');
}
} // end of class
所以有人用 that 先把 this 存起來, 然後在 callback method 裡面存取
使用 that 解決問題的版本
class MyClass{
initUI(){
let button = document.createElement('button');
button.innerHTML = 'ok';
const that = this;
button.addEventListener('click', function () {
// this => HTMLButtonElement
console.log('this.constructor.name = ', this.constructor.name);
// that => MyClass
console.log('that.constructor.name = ', that.constructor.name);
that.myFun(); // <--- OK
} );
}
myFun(){
console.log('myFun()');
}
} // end of class
class MyClass{
initUI(){
let button = document.createElement('button');
button.innerHTML = 'ok';
const that = this;
button.addEventListener('click', function () {
// this.constructor.name => MyClass
console.log('this.constructor.name = ', this.constructor.name);
this.myFun(); // <--- OK
}.bind(this) );
}
myFun(){
console.log('myFun()');
}
} // end of class
class MyClass{
initUI(){
let button = document.createElement('button');
button.innerHTML = 'ok';
const that = this;
button.addEventListener('click', => () {
// this.constructor.name => MyClass
console.log('this.constructor.name = ', this.constructor.name);
this.myFun(); // <--- OK
});
}
myFun(){
console.log('myFun()');
}
} // end of class