thisを理解する
thisは変数の宣言場所だけでは決まりません。通常関数の呼出し方、明示的な束縛、アロー関数の外側のthisを分けて、どのオブジェクトの値を読むかを追います。
この単元で学ぶこと
- 通常関数の受け手を呼出し式から求める
- call・apply・bindを使い分ける
- アロー関数とnewのthisを説明する
本文解説
受け手を表すthis const box={n:3,read(){return this.n;}};でbox.read()を実行すると3です。この通常メソッドのthisは呼出しの受け手boxです。thisはメソッド名でも戻り値でもありません。「どのオブジェクトに対する操作か」を同じ関数へ渡す仕組みと考えます。以下のコードは、特記がなければ新しいstrictモードの通常関数内で実行します。
定義場所より呼出し式 function read(){return this.n;}をa.readとb.readの両方へ代入しても関数は複製されません。a.n=2、b.n=8ならa.read()は2、b.read()は8です。通常関数が最初に保存されたオブジェクトへ固定されるわけではありません。関数の参照と受け手の情報を分けて追います。
メソッドを取り出したとき const f=box.read;f();ではbox.readという参照を値として取り出し、fを単独で呼んでいます。strictの通常関数のthisはundefinedとなり、this.nでTypeErrorです。非strict関数ではundefinedやnullのthisがグローバルオブジェクトへ置換される規則がありますが、この教材の実行条件へ混ぜません。コールバックへメソッドを渡すときにも、同様に受け手が失われるかを確認します。
callとapplyですぐに実行する function sum(x,y){return this.n+x+y;}に対しsum.call({n:10},2,3)は15です。callの第1引数がthisで、後ろが通常の引数です。sum.apply({n:10},[2,3])も15ですが、applyでは引数を配列状の値にまとめます。どちらもその場で関数を実行し、関数本体の戻り値を返します。
bindで呼出しを準備する const f=sum.bind({n:10},2);はthisと先頭引数2を保持した関数を返します。作っただけではsumは実行されません。f(3)で15となります。束縛後のf.call({n:99},3)でもthisは元のn=10のオブジェクトで、99へ置き換えられません。bindの戻り値を保存して使うことが大切です。
アローのthisは外側から function make(){return ()=>this.n;}をmake.call({n:7})で呼ぶと、返るアローは外側のthisを参照します。その関数へcall({n:1})しても結果は7です。アローをオブジェクトリテラルに書いたというだけでは、そのオブジェクトがthisになる保証はありません。外側の通常関数が何を受け手にして実行されたかを調べます。
newと新しい実体 function Item(n){this.n=n;}をnew Item(5)で呼ぶと、新しいオブジェクトをthisにして初期化します。通常のItem(5)とは呼出し方が違います。アロー関数はコンストラクタではなくnewで使えません。またclassで定義したコンストラクタはnewが必要です。変数名が大文字かどうかだけでは動作を判断できません。
値の保存と参照の保持 const a={n:3,make(){return ()=>++this.n;}};const f=a.make();ならf()はa.nを4に変えます。保持されるのはnのコピーではなく、外側thisを通じたオブジェクトへの参照です。通常関数なら呼出し方、bindなら束縛先、アローなら外側のthis、newなら生成対象という順で分類すると、似たコードを整理できます。
図解
重要ポイント
- 通常メソッドは呼出しの受け手でthisが決まる。
- strictの単独呼出しのthisはundefined。
- call/applyは実行、bindは関数生成。
- アローのthisは外側から得る。
間違えやすい点
- 関数を取り出しても元の受け手が付いてくると思わない。
- アローのthisをcallで上書きしない。
- strictと非strictの規則を混在させない。
用語解説
- 受け手
- obj.method()のobjのように、通常メソッドのthisとして使われる値。
- 束縛済み関数
- bindでthisや先頭引数を保持して作った呼出し可能な関数。
- 字句的this
- アローが独自のthisを作らず、外側の環境からthisを参照すること。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
- https://html5exam.jp/outline/objectives_lv2.html
- https://tc39.es/ecma262/2024/multipage/ordinary-and-exotic-objects-behaviours.html#sec-ordinarycallbindthis
- https://tc39.es/ecma262/2024/multipage/ecmascript-language-functions-and-classes.html#sec-class-definitions
- https://tc39.es/ecma262/2024/multipage/ecmascript-language-statements-and-declarations.html#sec-try-statement
確認問題の出題・採点や学習履歴の保存にはログインが必要です。