26

次の状況があります。

var large = [a,b,c,d,e,f,g,h,i];
var small = [a2, b2, c2, null, null, null, null, null, null, i2];

両方の配列のすべての要素がオブジェクトです。

小さな配列には、大きな配列に関連する情報が含まれていますが、 のすべての要素がlarge関連する要素を必要とするわけではないsmallので、 に設定しnullます。ただし、次のようなことができるように、インデックスを同じに保つ必要がありますlarge[16].id + ': ' + small[16].description。ほとんどが値の配列を持っているという事実は、nullメモリ使用量の増加につながりますか?

私の質問は、のようなことをしたりsmall = [a2,b2,c2,i2]、プロパティにインデックスを設定したりする方が良いかどうかa2.index = 0; b2.index = 1です。

また、代わりに undefined を使用するという提案に出くわし、誰かがリンクされたリストの実装について言及したことさえありました。要素を頻繁に追加または削除するわけではないので、リンクされたリストを実装する必要はないと思います。

4

4 に答える 4

20

配列は実際には、配列インデックスである名前を持つプロパティを特別に処理したオブジェクトです。

「null」を割り当てることにより、各プロパティが存在するようになります。これにより、ゼロ以外の量のメモリが使用され、前述のようにルックアップが遅くなります。

代わりに、存在しないメンバーを省略できます。これにより、スパース配列が生成されます。

var small = [a2, b2, c2,,,,,,, i2];
// small == [a2, b2, c2,undefined,undefined,undefined,undefined,undefined,undefined, i2]

配列要素(または任意の変数)に明示的に割り当てるとスペースundefined かかることに 注意してください。この場合にメモリを再利用するにdeleteは、要素を明示的に指定する必要があります。私のコードサンプルに示されている初期化スタイルは、省略された要素にも割り当てないため、それらはまったく存在しません。これは、配列オブジェクトのプロパティとしてこれらの要素の存在を確認することで確認できます。

// continued from above
small.hasOwnProperty('3'); // returns false

small[3] = undefined;
small.hasOwnProperty('3'); // now returns true because the property exists

delete small[3];
small.hasOwnProperty('3'); // returns false again

alert(small.length); // alerts '10', showing that the array itself is still intact.
于 2011-06-27T22:09:21.517 に答える
1

小さなアイテムをlarge[2].smallに入れてみませんか?とにかく、通常はjavascriptのメモリ消費について心配する必要はありませんが、未使用の位置を未定義のままにしておくことをお勧めします(これは、未定義に設定する以外の方法です)。これにより、javascriptエンジンが切り替えを決定できます。スパース配列(配列ではなくハッシュテーブルで表されます)。

于 2011-06-27T21:59:01.277 に答える
1

私はあなたの質問に完全に答えることができませnullundefined. しかし、これを行う標準的な方法は、Arrayコンストラクターを使用することだと思います。

var large = [1,2,3,4,5,6,7];
var small = new Array(large.length);
small.length; // 7
small[0]; // undefined

効果は同じですが、値を明示的に未定義に設定するよりもメモリ使用量が少ないと思います。これを 250,000 以上のインデックスを持つスパース配列に使用しましたが、メモリの問題は発生しませんでした (Google Chrome を使用)。

編集: (遊んでもう少し調査した後) 多くの人々はnew Array()、多くの理由でコンストラクターが好きではありません (たとえば、この議論を参照してください)。しかし、大規模なスパース配列にはいくつかの利点があると思います。

  • lengthプロパティを適切に設定します。配列の長さが大きな配列に一致する必要がある場合は、明示的に設定するsmall.length = large.lengthか ( )、末尾に未定義のものを配置する ( ) 以外では、これを行うことはできませんsmall[large.length-1] = undefined

  • 空のインデックスのキーを設定しないため、メモリの使用量が少ないと思います。a = [null,null,null]またはの配列がある場合a = [undefined,undefined,undefined]、これらの配列にはそれぞれ 3 つのインデックスがあり、a.mapまたはを使用するa.forEachと、インデックスごとに関数が呼び出されます。を使用a = new Array(3)してから呼び出すa.forEachと、関数は、構築後に値を明示的に設定したインデックスに対してのみ呼び出されます。

しかし、以下の間に大きなパフォーマンスの違いはないようです:

var a = new Array(2000); 
a[2000] = 1;

と:

var = [];
a[2000] = 1;

これにより、定義されたインデックスが 1 つだけの長さ 2000 の配列も得られます。したがって、 oflengthが of とsmall一致するかどうかを気にしない場合は、必要に応じて使用して動的にサイズ変更するだけです。特定のインデックスで値を設定および取得するという単純な観点からは、まったく同じです。lengthlargevar a = []

于 2011-06-27T21:59:26.393 に答える
1

Null は単語 'NULL' のサイズだけメモリを消費しますが (インタープリターに関して)、検索結果に移動しないオブジェクトで配列が圧倒されるため、検索が遅くなり、JS にはこれを最適化する方法。オブジェクトの配列をより適切に使用する必要があり、各オブジェクトは値とインデックスを保持する必要があります。

undefined の使い方もトリッキーです。解釈とスクリプトのサイズに関して、これはメモリを増やしますが、これは undefined がメモリを消費するかどうか、およびどれだけメモリを消費するかをアドバイスする仕様の一部ではないため、ガベージ コレクション、メモリ ヒープを消費する機能はブラウザ次第です。など。おそらく、試してみることが最善の方法です。Chrome 内で NULL と未定義の両方の比較的大きな配列を実行し、ヒープ スナップショットを取得して比較します。

于 2011-06-27T22:03:26.377 に答える