内部プロジェクトに使用しているArrayのサブクラスがあります。追加するメソッドのいくつかは、新しい配列を返す必要があります。その新しい配列を作成するための最良の方法を見つけようとしています。
特定のサブクラスの配列を作成するためにハードコーディングしたくありません。他の誰かが私のクラスをサブクラス化し、それがソース配列クラスである場合、そのサブクラスのオブジェクトを作成する必要があるためです。つまり、自分のthis
下にサブクラスがいくつあっても、現在のオブジェクトと同じクラスの新しいオブジェクトを作成したいと思います。
Arrayクラス自体はすでにこのようなことをしています。配列をサブクラス化して.map()
から、サブクラスのインスタンスで通常の関数を使用すると、クラスを使用して新しい配列が返されます。
このためのECMAScript仕様は、その用途のためにここに.map()
ありますArraySpeciesCreate()
.map()
が、実際のJavascriptコードの観点から、この仕様ロジックがすべて何に変換されるのか理解できません。
現在、私は使用しています:
let newArray = new this.constructor();
それは私自身の小さな世界で機能しているようですが、そのすべてのロジックにArraySpeciesCreate()
これよりも多くのコードが含まれるべきかどうか疑問に思っていますか?
参考ArraySpeciesCreate()
までに、これ.map()
は、返される新しい配列を作成するために従うことになっているECMAScript仕様からのものです。それは私がおそらく従おうとしていることでもあります。
これを自分のクラスに実装するために実際に使用するJavascriptコードは何ですか?
これが私のArrayサブクラスのメソッドの例です:
// break an array up into chunks
// the last chunk may have fewer items
// returns an array of arrays
chunk(chunkSize) {
if (!Number.isInteger(chunkSize) || chunkSize <= 0) {
throw new TypeError('chunkSize must be a positive integer');
}
const output = new this.constructor();
const numChunks = Math.ceil(this.length / chunkSize);
let index = 0;
for (let i = 0; i < numChunks; i++) {
output.push(this.slice(index, index + chunkSize));
index += chunkSize;
}
return output;
}
そのメソッドの次のコード行:
const output = new this.constructor();
私が質問しているのは、ArraySpeciesCreate()
ロジックを実装することになっているものです。
私はまだサブクラス化すべきではないとの意見を持っていますが、ECMAScriptで実装された場合にArray
どのようArraySpeciesCreate
に見えるかを示すことができます。
if (!Array.isArray(this)) // if not called on an array
return new Array(len);
const {constructor} = this;
if (typeof constructor == "function" // if the constructor looks like a constructor,
&& !Function.prototype.isPrototypeOf(constructor) // but appears to stem from a
// different realm (iframe etc)
&& constructor.name == "Array") // and might be that realm's builtin Array
return new Array(len);
const C = constructor?.[Symbol.species];
if (C == null) // if there's no subclass species
return new Array(len);
return new C(len);
とにかく実際には正確に機能していない、レルム間インスタンスのテストの奇妙なエッジケースを除外できる可能性があります。(私はこれらをチェックする良い方法があります疑う、再現することは不可能と思われるGetFunctionRealm -多分あなたが投げるしたいのにステップをいくつか チェックするためにconstructor
ネイティブ関数です)。
一般に、それは単ににアクセスSymbol.species
しthis.constructor
、新しいインスタンスを構築するために現在のクラスの代わりにその結果を使用することになります。
または、ごまかして使用することもできますArray.prototype.slice.call(this, 0, 0)
:-)
もう一つの良い解決策はある機能からES-抽象できるだけ正確として抽象的操作を実装しようとするライブラリー。ArraySpeciesCreate
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加