JavaScript数组的Splice方法无法正常工作

4
var cache = [];
cache[0] = "0";
cache[1] = "1";
cache[2] = "2";
cache[3] = "3";
cache[4] = "4";
cache["r"] = "r";
console.log(cache.length);
for(key in cache){
    if(isNaN(key))continue;
    else cache.splice(key,1); // cache.splice(key) is working fine, ***
}
console.log(cache);

问题: 在代码行 *** 中为什么 `splice(key)` 运行正常 (删除具有数字索引的所有元素),而 `splice(key,1)` 不正常 (不删除具有数字索引的元素)。我已经尝试过。
splice(key,1) // Not working as splice(key)
splice(key--,1) // Even not working as splice(key)
splice(key,0) // not deleting any thing

您可以将代码复制粘贴到Firebug控制台中进行测试。

3
你能解释一下“不起作用”是什么意思吗?当你尝试运行代码时会发生什么,与你预期的有什么不同?是否出现任何错误信息? - Guffa
splice函数从数组中删除元素。它应该删除所有数值索引的元素,但实际上只删除了一些。 - Wasim A.
splice函数期望我提供一个数字索引,因此(n,x)表示从数字索引n开始,并在索引n之后删除x个值。如果n不是数字而是一个键,则不需要x。所以当x被移除时,它可以正常工作。 - Wasim A.
不,没有索引是无法工作的。如果只指定一个参数,则该参数将用作索引,并且它将删除数组中所有项目直到结尾。如果您使用键而不是索引来调用方法并且它似乎有效,那只是巧合,因为您使用的特定值恰好产生了相同的结果。 - Guffa
3个回答

15
由于你在循环过程中删除了数组中的项目,因此它无法正常工作。当你删除一个项目时,它会根据数组的内部实现重新排列其他项目,这样你就得到了一个没有按预期迭代键的循环。
当我在Firefox中尝试时,它只遍历键“0”,“1”,“2”和“r”。在迭代过程中删除项目会使其跳过“3”和“4”。splice本身很好用,但它会影响循环,导致一些项目在迭代中被省略。
由于你实际上是想要通过跳过非数字键来查找数组中的索引,所以你可以直接循环遍历索引。通过向后循环,你不会遇到在循环过程中改变数组的问题。
var cache = ["0", "1", "2", "3", "4"];
cache.r = "r";
console.log(cache.length);
for (var i = cache.length - 1; i >= 0; i--) {
    cache.splice(i, 1);
}
console.log(cache);

Demo: http://jsfiddle.net/CguTp/1/


删除反向元素是个好主意,但我正在使用关联数组。你值得拥有。 - Wasim A.
我的问题是为什么splice(key,1)在同一个地方不起作用,而splice(key)却非常好用。 - Wasim A.
@Wasim:使用 splice(key) 不起作用,因为在这种情况下它只会给出相同的结果,代码试图删除所有项。它将在第一次迭代中从数组中删除所有项,而不是逐个删除一项。 - Guffa

3

1) cache["r"] = "r";不能将元素添加到数组中,它只是在缓存对象上添加了一个属性。

你可以使用以下方式初始化数组:

var cache = ["0", "1", "2", "3", "4", "r"];

或者

var cache = new Array();
cache.push("0");
cache.push("1");
cache.push("2");
cache.push("3");
cache.push("4");
cache.push("r");

由于您的缓存对象不是数组,您不能期望splice像对待数组一样运作。

2) splice的第一个参数应该是索引,而不是键

请参考http://www.w3schools.com/jsref/jsref_splice.asp

因此,您可以使用以下方法来删除所有数字值:

for (var i = 0; i < cache.length; i++) {
        if (!isNaN(cache[i])) {
            cache.splice(i, 1); // cache.splice(key) is working fine, ***
                i--;
            }
        }

在我的情况下,键或索引是相同的。我正在处理JavaScript的关联数组,而不是数字数组。请搜索Google了解关联数组和JSON的更多信息 :) - Wasim A.
根据这个问题的答案https://dev59.com/HkfSa4cB1Zd3GeqPAtxh,你可以使用delete而不是splice,这并没有回答为什么splice(key,1)不起作用,但显然这是从字符串索引数组中删除的正确方法。 - Eric Beaulieu
经过研究关联数组,我坚持我的答案。由于cache不是一个数组,你不能期望splice的行为像它一样。 - Eric Beaulieu
删除操作适用于 JSON 对象而不是 JS 数组。 - Wasim A.
精确地说,delete是用于JSON对象的,您的“cache”对象是一个JSON对象,而不是一个数组。 - Eric Beaulieu

2

Splice函数期望第一个索引为数字类型,

splice(n,x); //n and x are numeric here  

它将从索引n开始删除数组的值,并在索引n后删除x个值。

现在,如果n不是数字而是一个键,则不需要x,因为x只能在数值索引数组中向前移动指针,而不能在关联数组中。因此,从splice(n,x)中去除x将使函数类似于splice(key)等,因此它将正常工作。


我正在寻找一种从关联数组中删除元素的好方法。根据这个答案,这个 应该可以工作,但是,如控制台所示,它对关联数组没有任何影响。使用 delete 将会起作用,就像 这个例子 一样(尽管 .length 属性似乎功能异常)。 - JVE999
splice(key) 应该可以正常工作,而 splice(key,x) 将无法正常工作。只需从 splice 函数中删除第二个参数即可。 - Wasim A.
你找到的答案是正确的吗?让我检查一下,如果那个答案更好,我会选择它。 - Wasim A.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接