我有一种情况,我必须从数组vs .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
***让我清楚一点。这些childNodes包含在数组中的文档片段中。这些childNodes不在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; };
};
};
答案 0 :(得分:2)
childNodes
是实时 NodeList,因此每次删除项目时,列表都会缩短,因此您可以有效地跳过每个第二个节点。如果要从文档片段中删除所有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
的节点。简单来说,它会删除每一个孩子。
此外:
> if (uncheckedQue[i].childNodes.length < 1) {
可以是:
if (!uncheckedQue[i].childNodes.length) {
因为NodeList的length value是0的无符号整数,如果length为零,则测试返回true。
要从数组中删除片段,请按照VeXii的建议使用Array.prototype.splice。但请注意,您必须调整索引或在数组中向后工作,原因与删除实时NodeList成员时的原因相同。
你会注意到为什么我使用删除,所以我保持我的长度正确的外循环。
因为delete运算符不调整数组成员索引(它们只是属性名称),所以你有一个稀疏数组。你可以使用splice并随意调整索引,或者在数组中向后移动,或者在末尾压缩数组(这可能是性能最差的解决方案),例如。
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
的成员或其他一些虚假值,只会删除那些根本不存在的成员。
答案 1 :(得分:1)
而不是删除使用拼接像
if (uncheckedQue[i].childNodes.length < 1) {
uncheckedQue.splice(i,1)//remove the document fragment if has no childnodes
};