継承のブラウザ挙動/実装演習
親と子のメソッドが重なるコードを、呼出し・初期化・戻り値の三つに分けて追います。多段継承、static、親メソッドの更新を組み合わせ、どの値が最終結果になるかを確かめます。
この単元で学ぶこと
- constructorの実行順と引数を計算する
- 多段のsuper呼出しとstaticのthisを追う
- 親の変更と例外が派生側へ与える影響を説明する
本文解説
引数の加工と初期化を順に計算する 親Aがconstructor(n){this.n=n*2;}、子Bがconstructor(n){super(n+1);this.n+=3;}ならnew B(4).nは13です。子が4を受け、親へ5を渡し、親が10にして戻り、子が3を足します。単にソースの上から数字だけを拾わず、引数の受渡しを矢印にします。
super前にできる処理 派生constructorのsuper前でも、引数の検査や外部配列への記録など、thisを使わない処理は行えます。log.push("before");super();log.push("after");なら親がAを記録するとbefore,A,afterです。「superより前には一切の文を書けない」という暗記では、thisが未初期化という本当の理由を見失います。
多段継承の戻り順 A.value()がA、B.value()がsuper.value()+"B"、C.value()がsuper.value()+"C"を返すとします。new C().value()の呼出しはC→B→Aと進み、戻るときにA→AB→ABCと結果を作ります。呼出す順と文字を付け足す順は逆方向です。superは一段上を起点にするため中間のBを飛ばしません。
メソッドの探索は後からも変わる A.prototype.mを新しい関数へ置き換えれば、子のsuper.m()も現在のその関数を使います。親が5を返し、子がsuper.m()*2なら結果は10です。またdelete B.prototype.mで子の上書きを消すと、b.m()は親のmを探索します。既存実体が古いメソッドをコピーして固定しているわけではありません。
staticでも受け手を分ける 親のstatic read(){return this.label;}をB.read()で呼ぶとthisはBです。A.label="A"、B.label="B"なら結果はBです。子のstaticからsuper.n()を呼ぶ場合、探すのはA.prototypeでなく親コンストラクタA側です。実体メソッドの経路とstaticの経路を二本で確認します。
superの探索先とcallの受け手 Bのm(){return super.m()+1;}をconst f=B.prototype.m;で取り出してf.call({n:10})と呼べます。親mがthis.nを返すなら11です。superで親を探す位置はメソッドの定義に結び付いたままで、thisはcallが指定します。superを「thisの親」とだけ覚えると、この二つを混同します。
生成ごとの状態と親の失敗 親constructorでthis.items=[]を作れば、子の実体a,bは別配列を持ちます。一方、親constructorがthrowした場合、子のsuper後の行は正常な続きとして実行されません。外側のcatchへ移り、失敗した生成の途中へ戻るわけでもありません。初期化済みの実体を得た前提で処理を続けないことが重要です。
継承関係を逆向きにしない new B()は通常AとB両方のinstanceofを満たしますが、new A()がBに属するとは限りません。親から子への特化という方向があります。値がないときは実体の所有プロパティ、子prototype、親prototypeの順に確認し、上書きの有無と構築時の初期化をそれぞれ切り分けます。
図解
重要ポイント
- 親へ渡す前の計算と親から戻った後の計算を分ける。
- super前でもthisを使わない処理は可能。
- staticのthisも呼出しの受け手で決まる。
- 親のthrow後に派生constructorの正常な続きを実行しない。
間違えやすい点
- superの探索位置とthisを同一視しない。
- 親実体を必ず派生型だと判断しない。
- 削除後にどの段階のメソッドが見えるか確認する。
用語解説
- 多段継承
- CがBを、BがAを継承するように複数段の探索関係を作ること。
- 初期化順序
- 親へ渡す処理、親の構築、派生側の追加処理が実行される順番。
- 伝播
- 捕捉されていない例外などが呼出し元へ伝わること。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
- 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
確認問題の出題・採点や学習履歴の保存にはログインが必要です。