thisのブラウザ挙動/実装演習

メソッドの受渡しは、処理そのものと受け手の情報を切り離すことがあります。配列コールバック、bindの引数、newを含むコードを実行順に追い、安全に意図した対象を操作する方法を学びます。

この単元で学ぶこと

  • メソッド移動と共有状態を追跡する
  • コールバックへ受け手を渡す方法を選ぶ
  • 束縛とnew・アローの優先関係を判定する

本文解説

同じ関数を別の対象へ置く const a={n:1,inc(){return ++this.n;}};const b={n:10,inc:a.inc};とします。b.inc()は11で、a.nは1です。関数本体が共有されても、nを保存するオブジェクトは別です。メソッド名や定義位置より、各呼出しでどの参照が受け手になるかを表にします。

引数の一部を先に固定する function sum(a,b){return this.n+a+b;}にsum.bind({n:10},2)を適用すると、thisと最初の引数を保持します。得られたfにf(4)を実行したときはa=2,b=4で16です。bindの先頭はthis用の枠なので、通常引数を一つずつずらして読む必要があります。

束縛後も対象は変化する const a={n:2};const f=read.bind(a);の後a.n=9にすると、readがthis.nを返す場合f()は9です。bindはオブジェクトのスナップショットを作りません。f.bind({n:8})を作っても元のthis=aは上書きされないため、対象を切り替えたいなら元のreadから新しくbindします。

内側の関数を比較する obj.run()の中でfunction f(){return this;}と書いてf()を呼ぶと、strictではundefinedです。通常関数は外側のthisを自動継承しません。一方const f=()=>this;なら外側runのthisを読みます。ネストしていること自体ではなく、どちらの関数記法を使ったかが分岐点になります。

mapへ渡す二つの方法 const a={n:5,read(){return this.n;}};に対し[1,2].map(a.read.bind(a))は[5,5]です。[1,2].map(a.read,a)も、mapの第2引数thisArgを通常コールバックへ渡すので同じ結果になります。ただしコールバックがアローならthisArgで外側thisは変えられません。APIの引数仕様と関数の種類を両方確認します。

取り出した関数を明示して呼ぶ const {read}=a;は分割代入で関数値を得る操作です。read()では受け手を失いますが、read.call({n:12})なら12を返せます。aが書かれていた構文から関数を得たことと、その後の関数にaが束縛されていることは別です。取り出した時点と呼んだ時点を二行に分けて追います。

束縛したコンストラクタ function Item(n){this.n=n;}、holder={n:1}、Bound=Item.bind(holder,7)を考えます。new Bound()はholderへ代入するのでなく、新しい実体のnを7にします。newでは束縛済みthisを使わず、束縛済み引数は適用します。アローは元々構築可能でないため、bindしてもnewで使えるようにはなりません。

関数の返却だけではthisは固定されない a.make()がfunction(){return this.n;}を返す場合、その通常関数をb.fへ保存してb.f()を呼べばthisはbです。返した関数が()=>this.nならa.make()の外側thisを参照します。通常関数・アロー・束縛済み関数の三種類を区別すると、返却関数を使う設計でも結果を説明できます。

図解

関数を受け渡すときの三つの分岐
同じ関数の見た目でも、thisを決める経路が違う。

重要ポイント

  • bindは対象の現在のプロパティを読み続ける。
  • mapのthisArgは通常関数へ渡せる。
  • newでは束縛済みthisより生成した実体が使われる。
  • 返却した通常関数は新しい呼出し先でthisが決まる。

間違えやすい点

  • bindの生成と関数の実行を混同しない。
  • メソッド共有を状態の共有と決めつけない。
  • オブジェクトを返すアローをコンストラクタと思わない。

用語解説

thisArg
callや配列メソッドなどが、呼ぶ通常関数のthisとして指定する引数。
部分適用
いくつかの引数を先に固定し、残りを後から与えること。
構築可能
newによるオブジェクト生成の呼出しを受け付ける性質。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。