それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

ES/JavaScriptのthisとアロー演算子について知っておくべきこと

this. この便利でハマりどころの多い変数

Array.forEach / map 系 のthisArg が安定しない。

this 変数の紹介 this 変数の例

apply , call

window オブジェクト コールバック イベントハンドラ Array.forEach

個人的な結論 this はできるだけ避ける

調べたキッカケは Array.forEach

arr = ["A","B","C"]
arr.forEach(  function ( x ) { console.log ( this ) }  )

このthisとして this => [“A”,“B”,“C”] を期待したわけです。

でも、this = window

arr = ["A","B","C"]
arr.forEach(  function ( x ) { console.log ( this ) }  )
//=> Window
//=> Window
//=> Window

え?Windowなの?ちょっとまって。this 。そうか、そうだった。

"abc".replace( /a/, function(x){return this} )
//=>"[object Window]bc"

そういえばそうでした。this は関数の定義されたスコープから探されますよね。

this はその関数が実行(無名関数なら定義)されたスコープになる。

JSの変数はその実行スコープで決まる。

arr.forEach(  function ( x ) { console.log ( this ) }  ) // ここはWindowが実行するので this = window

実行主体がWindowなのでthis=window 、匿名関数なので定義されたタイミングでthis が決まる。

でもコレを見て欲しい(もう謎すぎてヤバイ)

アロー演算子と、function で指定し場合

f:id:takuya_1st:20160602152936j:plain:w400

実行環境は次の通り

f:id:takuya_1st:20160602153206j:plain:w300

ちなみに use strict すると動作が変わる

f:id:takuya_1st:20160602154225j:plain:w400

function の場合は use strict すれば次のような動作になる。

function を匿名関数で渡した場合

ソース thisArg use strict 結果(this参照先)
arr.forEach( function(x){console.log(this);} ) なし なし Window
arr.forEach( function(x){“use strict”; console.log(this);},arr ) arr なし arr
arr.forEach( function(x){“use strict”; console.log(this);} ) なし あり undefined
arr.forEach( function(x){“use strict”; console.log(this);},arr )) arr あり arr

function を アロー演算子で渡した場合

ソース thisArg use strict 結果
arr.forEach( (x)=>{console.log(this);} ) なし なし Window
arr.forEach( (x)=>{console.log(this);}, arr ) arr なし Window
arr.forEach( (x)=>{“use strict”;console.log(this);}) なし あり Window
arr.forEach( (x)=>{“use strict”;console.log(this);}, arr ) arr あり Window

アロー演算子ではすべてが window(グローバル)です

forEach した場合ね

なにこれ揺れすぎ

ていうか、アロー演算子は this の値を、オブジェクト定義から参照する。

forEach引数 で this の値を指定しても、実行してるスコープが window なので強制的に Window (グローバルオブジェクト)になる。

アロー演算子でのforEachでは再束縛が出来なくなってる。。。。

もうね、this使うなとしか言いようが無い。

結論 this 使うな

暴論しておきたい。

参考資料

thisArgs について

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Lexical_this

this について

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

感想

無名関数のときに"use strict" した forEach で thisArg 無しならで undefined になる。これが個人的にはキッチリしてて嬉しいよね。いかにもuse strict っぽい。

アロー演算子の場合 this なかったら強制グローバルってのはどうも腑に落ちてこないというか。

コレクションでforEach中のthis は定義元のオブジェクトより、コレクション自身をしてして欲しいような気はする。

forEach がネストした時とか特に。

forEach が導入されて数年になるけど、あっさり thisArgs がなかったような扱いになってるのが寂しい所。

追記 2017-06-02

this が云々というより、thisArgs について語りたかった。アロー演算子の this はグローバルなので、 map( f , thisArg ) で thisArg を指定しても無視されるって話がメイン。

使うか使わないかとか、forEachの第三引数の話が使う使わないとか、this そのものの理解がとか、ブクコメに云々もについても言いたいことは、あるけれど 現状 use stricit してるかチェックを油断してるとまじthisめんどーってなる。コーディング規約が決まった同一社コードばかり見てるわけじゃないんで。油断するなよ的な、そんな話