0

配列と .splice から obj を削除しなければならない状況があります。以下に示すように、配列が正しく再番号付けされていないことが原因です。

配列のオブジェクトを削除した後、配列内の未定義のプレースホルダーを取り除くには、[].concat() を実行します。これに関する問題は、新しい配列が正しく番号付けされていないことです。

低いオーバーヘッドで新しい配列を正しく再番号付けするには、何が最も効果的ですか?

for (var o = 0; o < uncheckedQue[i].childNodes.length; o += 1) {
    uncheckedQue[i].removeChild(uncheckedQue[i].childNodes[o]);
    if (uncheckedQue[i].childNodes.length < 1) {
        delete uncheckedQue[i];//remove the document fragment if has no childnodes
    };
};

 uncheckedQue = [].concat(uncheckedQue);


0: DocumentFragment
2: DocumentFragment
3: DocumentFragment
4: DocumentFragment
5: DocumentFragment
6: DocumentFragment
7: DocumentFragment
length: 8

***何かを片付けさせてください。これらの childNode は、配列内のドキュメント フラグメントに含まれています。これらの childNode は Dom にはありません。

これが外側のループです。削除を使用する理由に気付くと思いますので、外側のループの長さを正しく保ちます。

     for (var i = 0; i < uncheckedQue.length; i += 1) {
                 //
                 if (t.mucs === t.mucsstop) { break; };
                 for (var o = 0; o < uncheckedQue[i].childNodes.length; o += 1) {
                     uncheckedQue[i].removeChild(uncheckedQue[i].childNodes[o]);
                     t.mucs += 1;
                     if (uncheckedQue[i].childNodes.length < 1) {
                         delete uncheckedQue[i];//remove the document fragment if has no childnodes
                     };
                     if (t.mucs === t.mucsstop) { break; };
                 };
             };
4

2 に答える 2

2

childNodesライブNodeList であるため、アイテムを削除するたびにリストが短くなるため、2 つおきのノードを効果的にスキップできます。ドキュメント フラグメントからすべての childNodes を削除する場合、最も簡単な方法は、firstChild ノードがなくなるまで削除し続けることです。

var node = uncheckedQue[i];
while (node.firstChild) {
  node.removeChild(node.firstChild);
}

また、NodeList はホスト オブジェクトであり、配列ではないため、配列メソッドを呼び出すとエラーがスローされます。

編集

あなたのコードから:

> for (var o = 0; o < uncheckedQue[i].childNodes.length; o += 1) {

これは、一般的な形式でより明確になります。

for (var j=0; j < uncheckedQue[i].childNodes.length; j++) {

uncheckedQueがドキュメント フラグメントの配列の場合、次のようになります。

> uncheckedQue[i].removeChild(uncheckedQue[i].childNodes[o]);

フラグメントから子ノードを削除しています。したがって、現在の子ノードchildNodes[o]は、childNodes[o + 1]そのステートメントが実行される前の子ノードです。したがって、次の反復では、o + 1ノードは以前にあったノードになりますo + 2。簡単に言えば、2 つおきの子が削除されます。

また:

> if (uncheckedQue[i].childNodes.length < 1) {

次のことができます。

if (!uncheckedQue[i].childNodes.length) {

NodeListの長さの値は 0 からの符号なし整数であるため、長さがゼロの場合、テストは true を返します。

配列からフラグメントを削除するには、VeXiiで提案されているように Array.prototype.splice を使用します。ただし、ライブ NodeList のメンバーを削除する場合と同じ理由で、インデックスを調整するか、配列を逆方向に操作する必要があることに注意してください。

削除を使用する理由に気付くと思いますので、外側のループの長さを正しく保ちます。

delete 演算子は配列メンバーのインデックス (単なるプロパティ名) を調整しないため、スパース配列になります。スプライスを使用してインデックスを調整するか、配列を逆方向に移動するか、最後に配列を圧縮することができます (これはおそらく最悪のパフォーマンスのソリューションです)。

function compressArray(a) {
  for (var i=0; i<a.length; i++) {
    while (!a.hasOwnProperty(i) && a.length > i) {
      a.splice(i, 1);
    } 
  }
  return a;
}

上記は元の配列を変更することに注意してください。配列メンバーを新しい配列にコピーする方が簡単です。

function compressArray(a) {
  for (var i=0, iLen=a.length, b=[]; i<iLen; i++) {
    if (a.hasOwnProperty(i)) {
      b.push(a[i]);
    } 
  }
  return b;
}

好きなのを選びな。どちらのメソッドも、値がundefinedまたはその他の偽の値を持つメンバーを削除し、まったく存在しないメンバーのみを削除することに注意してください。

于 2012-10-28T23:41:57.020 に答える
1

delete の代わりに splice を使用

if (uncheckedQue[i].childNodes.length < 1) {
   uncheckedQue.splice(i,1)//remove the document fragment if has no childnodes
};
于 2012-10-28T23:38:03.000 に答える