JavaScriptのthisの扱いは少し注意が必要です。
参考記事: JavaScriptの「this」は「4種類」??
ES2015のclassでもそれは同じこと。
下記のように呼びだされ方で結果が変わります。
index.js
'use strict';
class Message {
constructor(message) {
this.message = message;
}
show() {
try {
console.log(this.message);
} catch (e) {
console.error(e);
}
}
}
var m = new Message('Hello!');
m.show();
// Hello!
var show = m.show;
show();
// [TypeError: Cannot read property 'message' of undefined]
setTimeout(m.show, 0);
// undefined
thisを自インスタンスとして扱わせるには下記のような方法があります。
bindを使用
classメソッドも所詮はfunctionなのでbindメソッドでthisを明示できます。
http://stackoverflow.com/questions/31362292/can-i-use-es6-arrow-in-class-methods
index.js
'use strict';
class Message {
constructor(message) {
this.message = message;
this.show = this.show.bind(this);
}
show() {
try {
console.log(this.message);
} catch (e) {
console.error(e);
}
}
}
var m = new Message('Hello!');
m.show();
// Hello!
var show = m.show;
show();
// Hello!
setTimeout(m.show, 0);
// Hello!
constructor内でarrow functionを使用
arrow functionがthisの参照先を変えないことを利用してconstructorでメソッドを定義します。
index.js
'use strict';
class Message {
constructor(message) {
this.message = message;
this.show = () => {
try {
console.log(this.message);
} catch (e) {
console.error(e);
}
};
}
}
var m = new Message('Hello!');
m.show();
// Hello!
var show = m.show;
show();
// Hello!
setTimeout(m.show, 0);
// Hello!
classを使う側で対処
index.js
'use strict';
class Message {
constructor(message) {
this.message = message;
}
show() {
try {
console.log(this.message);
} catch (e) {
console.error(e);
}
}
}
var m = new Message('Hello!');
m.show();
// Hello!
var show = m.show.bind(m);
show();
// Hello!
setTimeout(m.show.bind(m), 0);
// Hello!
setTimeout(() => {
m.show();
}, 0);
// Hello!