転職先の業務でReactを使うので勉強していたところ、公式Docs中の文で分からなかった箇所があったので調べてまとめました。ぱっと見て分からない場合は、ぜひ読み進めていただけると分かると思います。
JavaScriptにおいて、以下の2つのコードは同等ではありません。
https://ja.reactjs.org/docs/faq-functions.html より
obj.method();
var method = obj.method;
method();
実行コンテキストによってthisの参照先が異なる
どっちも同じことをしているのではないかと思われたかもしれません。しかし、オブジェクトの中にthisが存在すると話が変わってきます。
window.name = 'Suzuki';
const obj = {
name: 'Sakai',
method: function() {
console.log('Hello! ' + this.name);
}
}
obj.method(); // Hello! Sakai
var method = obj.method;
method(); // Hello! Suzuki
ここで大事なのが、thisが何を参照するかです。
オブジェクトのメソッドとして実行される場合、thisは呼び出し元のオブジェクトを参照します。一方、関数として実行される場合、グローバルオブジェクトを参照します。
obj.method()
の形で実行された場合、method
はオブジェクトのメソッドとして実行されているので、this
は呼び出し元のオブジェクト、つまりobj
を参照します。従って、コンソールにはHello! Sakai
が出力される。
一方、var method = obj.method;
で変数method
に関数の形で保存され、method()
でその関数が実行される形になるので、this
の参照先はグローバルオブジェクトとなる。従って、コンソールにはHello! Suzuki
が出力される。
参照先のオブジェクトを固定するにはbindを使う
this
を使う場合に注意が必要なのは、分かっていただけたかと思います。ただ、
関数として実行してかつobj
のname
を参照したい場合もあるかと思います。そういうときはbind
を使います。
window.name = 'Suzuki';
const obj = {
name: 'Sakai',
method: function() {
console.log('Hello! ' + this.name);
}
}
obj.method(); // Hello! Sakai
var method = obj.method.bind(obj);
method(); // Hello! Sakai
var method = obj.method.bind(obj)
のようにbindメソッドを使います。これは、bindの引数のオブジェクトをmethod
の中で実行されるthis
の参照先として設定しています。そうすることで、関数として実行してもthis
の参照先がobj
にバインド(英語で結びつけるという意味です)されているので、obj.method()
と同じ結果が得られます。
さいごに
最初に戻ると、bindを使ってやると下の2つのコードは同等になります。
obj.method();
// var method = obj.method
var method = obj.method.bind(obj);
method();
何か間違いや分かりにくいところがあれば教えてくださると幸いです。
ここまで読んでいただきありがとうございました。