JSのbind、及び`this`について理解を少し深める
bindそのものについて
JSのbindの用法を知り、「どういう時に使われるのか」が漠然とイメージできるようになりたかったため、概要と使われ方を調べた。
とりあえず以下のサイトのデモコードを自分なりにいじってどういう挙動なのかは調べた。
Function.prototype.bind() - JavaScript | MDN
const module = { a: 50, b: 30, text: 'this is test', showText: function(){ return this.text; }, }; const moduleShow = module.showText; console.log(moduleShow); // moduleから抜き出した関数にmodule自体をbindする // moduleShow内のthis = bindされたmoduleとなる // そのため、this.text = module.text、になる const boundGetX = moduleShow.bind(module); console.log(boundGetX());
その他、bindの概要、callとの違いについては下記の記事を見てイメージは出来た。 JavaScript thisの内容を指定する(bindメソッド) | ITSakura
ただ、こいつがどういう目的で使われるかは分からなかった。*1
単純に、関数内のthis(thisがない場合はbind内の第一引数にnullを指定する)を特定のものに設定する(=undefinedにしない)場合にbindを使う、という使い方でいいのだろうか。
アロー関数内でのthisの扱われ方とbindの比較
ここまで調べて、そういえばJSの通常関数とアロー関数ではthisの指すものが異なる、という話しを思い出した。
【JavaScript】アロー関数式を学ぶついでにthisも復習する話 - Qiita
JavaScript: 通常の関数とアロー関数の違いは「書き方だけ」ではない。異なる性質が10個ほどある。 - Qiita
両者のthis
に関する違いとしては、アロー関数はthis
を束縛し、通常関数はthis
を束縛しない(=関数呼び出し元(レシーバ)をthisとする)という点である。
下記のコードを例に比較する。
- 通常関数
this.name = "globalName"; // 通常関数 function showName() { console.log(this.name); } let arrowFunc = { name: "john", func: showName, }; arrowFunc.func(); => john // bindを使った場合 showName.bind(arrowFunc)(); => john
arrowFunc.func()
の返り値がjohn
となっており、これはarrowFunc.nameの値であることが分かる。
このことから、arrowFunc.func()
、つまりはarrowFunc.showName()
のshowName内部のthisはarrowFunc(レシーバ)を指していたことが分かる。
- アロー関数
this.name = "globalName"; // アロー関数 const showName = () => { console.log(this.name); }; let arrowFunc = { name: "john", func: showName, }; arrowFunc.func(); => globalName
arrowFunc.func()
の返り値が「globalName」となっている。これは最初に定義したthis.name = "globalName"
のnameの値が表示されていることが分かる。
ここで、アロー関数内のthisについてのリファレンスを見てみる。
アロー関数自身は this を持ちません。レキシカルスコープの this 値を使います。つまり、アロー関数内の this 値は通常の変数検索ルールに従います。このためスコープに this 値がない場合、その一つ外側のスコープで this 値を探します。
アロー関数であるshowName
が定義された際、関数内のthisは更に外側のthisを見ていたことになる。
今回Node上で上記コードを実行したため、thisとして定義されていたのは{name: "globalName"}
だったため、showName
関数内のconsole.logで表示されたthis.nameは、コードの最初に定義したthis.nameだった、ということになる。
ちなみにトップレベル、グローバルスコープあたりはここを参考にした。
JavaScriptのトップレベルスコープは常にグローバルスコープではなかった - Qiita
まとめ
改めてbind
、通常関数とアロー関数それぞれでのthisの使い方を確認した。
通常関数とアロー関数の違いについては他にも色々あるが、一旦知りたいと思っていたことを確認することができた。