3

Array から継承された新しい JavaScript オブジェクトを作成する必要がある状況があります。次のコードを使用しています。

// Create constructor function.
var SpecialArray = function () {};

// Create intermediate function to create closure upon Array's prototype.
// This prevents littering of native Array's prototype.
var ISpecialArray = function () {};
ISpecialArray.prototype = Array.prototype;
SpecialArray.prototype = new ISpecialArray();
SpecialArray.prototype.constructor = SpecialArray;


// Use Array's push() method to add two elements to the prototype itself.
SpecialArray.prototype.push('pushed proto 0', 'pushed proto 1');

// Use [] operator to add item to 4th position
SpecialArray.prototype[4] = 'direct [] proto to 4';

// Create new instance of Special Array
var x = new SpecialArray();

// Directly add items to this new instance.
x.push('pushed directly on X');
x[9] = 'direct [] to 9'

console.log(x, 'length: ' + x.length);

非常に興味深いことに、 [] 操作は役に立たないようで、コンソール出力は次のようになります。

["pushed proto 0", "pushed proto 1", "pushed directly on X"] length: 3

ここで何が欠けていますか?

4

3 に答える 3

4

Array クラスをサブクラス化し、この方法で t を使用することはできません。最善の解決策は、配列クラスだけを拡張してそのまま使用することです。私が好きではない他の2つのオプションがありますが、それらは存在します

于 2010-07-21T13:18:21.270 に答える
3

これは、常に人々をつまずかせるものの1つです。length プロパティは、順序付けされた要素にのみ適用されます。配列を拡張してから、任意の非連続キーを挿入して、それが機能することを期待することはできません。これは、配列を拡張すると、長さプロパティと配列の内容との関係が壊れるためです。上記の Pointy のリンクは、これをより詳細に説明するのに非常に優れています。

これを証明するには、これを例の最後に追加します。

console.log(x[4]);

エントリが存在し、正しいことがわかるように、それは順序付けられた配列の一部ではありません。

JavaScript の他のすべてと同様に、Array オブジェクトは文字列キーを持つ連想配列です。非数値、非連続キーは隠されているため、「適切な」数値インデックス配列であると思わせることができます。

Array オブジェクトのこの奇妙な混合設計は、順序付けられた情報と順序付けられていない情報を同じオブジェクトに格納するなど、いくつかの奇妙で素晴らしいことを実行できることを意味します。これが良い考えだと言っているのではなく、可能だと言っているだけです。

このように構造を反復するとき、非連続キーが表示されないことに気付くと思いますが、これは、順序付けられた情報に対する配列の一般的な使用例では意味があります。キー付きの情報を取得したい場合は、あまり役に立たないか、実際には役に立ちません。順序付けが重要でない場合は、配列ではなくオブジェクトを使用する必要があります。順序付きと順序なしの両方が必要な場合は、配列をプロパティとしてオブジェクトに格納します。

于 2010-07-21T13:12:40.283 に答える