質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

コンストラクタ

オブジェクト指向言語において、オブジェクトを生成時に呼び出され、データの初期化などを行なう関数・メソッドのことである。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

1229閲覧

Arrayを継承したサブクラスのコンストラクタ呼び出しタイミングについて

amtt

総合スコア1

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

コンストラクタ

オブジェクト指向言語において、オブジェクトを生成時に呼び出され、データの初期化などを行なう関数・メソッドのことである。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/08/21 13:57

分からない点

Arrayを継承したサブクラス (以下"newArray"とします) からArrayのmapメソッドを呼び出そうとしているのですが、この際、意図せぬタイミングでnewArrayのコンストラクタが呼び出されてしまう原因を知りたいと考えています。

ソースコード例

JavaScript

1(()=>{ 2 class newArray extends Array{ 3 constructor(f, x){ 4 super(...x); 5 this.f = f; 6 return this; 7 } 8 9 add(y){ 10 const temp = this.map((e, i) => e + y[i]); 11 return new newArray(this.x, temp); 12 } 13 } 14 15 const a = new newArray(undefined, [1, 2, 3]); 16 const b = a.add([0, 1, 2]); 17 18 console.log(a, b); 19})();
  • コンソールに"[1, 2, 3], [1, 3, 5]"と出力されることを期待しています。
  • (コンソールでの確認を目的としているため)グローバルで関数・変数定義されないように無名関数で囲んでいます。
  • コンストラクタ引数やプロパティとしてののfにはxを引数に取る関数を入れる予定ですが、主旨とあまり関係ないため処理等の記述を割愛しています。

エラーメッセージ

上記コードをFirefox (91.0.1 64ビット) のコンソールにそのまま貼り付けて実行した際のエラー出力です。Chrome/Edgeでも同様でした。
最も環境は関係なく、仕様の理解不足によるものと考えていますが…。

Uncaught TypeError: x is undefined newArray debugger eval code:4 add debugger eval code:10 <anonymous> debugger eval code:16 <anonymous> debugger eval code:19 debugger eval code:4:13

試したこと

以下について確認したのですが結局原因は掴めず、お知恵を拝借したい所存です。

  • 10行目のmapメソッド呼び出しの直前(?)にnewArrayのコンストラクタ呼び出しが発生していること
  • コンストラクタの引数が(f = 3, x = undefined) で呼び出されており、xの展開に失敗していること
  • this.map ⇒ super.map に変えても変化ないこと

以上です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

10行目のmapメソッド呼び出しの直前(?)にnewArrayのコンストラクタ呼び出しが発生していること

それがmapの仕様です(ECMA-262)。

その際に、コンストラクタは**「長さを表す数値」の1引数**で呼び出されます(ECMA-262)。

つまり、引数を増やしたコンストラクタを持つnewArrayは、mapが期待するコンストラクタを持っていない、という結論です。

投稿2021/08/21 14:11

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

amtt

2021/08/21 14:40

なるほど、迅速なご回答ありがとうございます。助かりました。 super経由でmapを呼びだしても呼び出されるコンストラクタを指定することはできないようですね。 解決策の方針として例えば以下のようなものを考えておりますが、他にもっとスマートな案がございましたらご教示いただけないでしょうか。 ・Array.prototype.map.callで無理やり適用 ・そもそもmapを使わない
maisumakun

2021/08/21 14:58

mapもオーバーライドする、というのはどうでしょうか。 なお、 > Array.prototype.map.callで無理やり適用 これは役に立ちません。オブジェクトからコンストラクタを探し出します。
amtt

2021/08/22 02:52

>> Array.prototype.map.callで無理やり適用 > これは役に立ちません。オブジェクトからコンストラクタを探し出します。 仰るとおりです。失礼いたしました。 > mapもオーバーライドする 取り急ぎ動作確認はArray.fromを噛ませることでお茶を濁しましたが、実際の想定ではそれなりの頻度で呼び出されること(Arrayインスタンス再生成のコストが懸案)や、可読性なども考慮するとそれがベストのように思えてきました。 この辺の考察は今後の私の宿題にしようと思います。 何はともあれ動作まで漕ぎ着けました。重ねてお礼申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問