【问题标题】:In javascript, how do I remove an element from an array of objects?在javascript中,如何从对象数组中删除元素?
【发布时间】:2011-03-14 23:20:18
【问题描述】:

在 javascript 中,如何从对象数组中删除元素? 代码如下:

$.fn.mapImage.deletePinpoint = function(image, pinpoint){
    var deleted = false;
    for (var i = 0; i < image.pinpoints.length; i++) {
        if(image.pinpoints[i].position == pinpoint.position){
            image.pinpoints.remove(i);
            deleted = true;
        }
        if(deleted){
            image.pinpoints[i].position -= 1;
        }
    }
    $('.edit-mode').find('div.dynamic-pinpoint-area').remove();
    $('.edit-mode').find('div.pinpoint-text').remove();
    $('.create-mode').find('div.static-pinpoint-area').remove();
    $('.create-mode').find('div.pinpoint-text').remove();

    $.fn.mapImage.load(image);

}

image.pinpoints 是对象数组。再次感谢大家!

【问题讨论】:

  • 您是否有机会查看此问题的其他答案并接受合适的答案?接受的答案链接到带有恶意软件的网站,并没有真正解释为什么splice() 是执行此操作的首选方式。谢谢。

标签: javascript jquery jquery-ui jquery-plugins


【解决方案1】:

https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator

例如(来源)

var trees = ["redwood","bay","cedar","oak","maple"];  
delete trees[3];  
if (3 in trees) {  
   // this does not get executed  
}  

【讨论】:

  • 请注意,如果您使用 delete 而不是 splice 它不会对您删除的索引之后的元素重新编号。如果您使用 'in' 语法,这很好,但在使用 for 循环时可能会导致麻烦。 for(var i=0;i
  • 这是真的。这也是为什么 for (i in arr) 在许多情况下更可取的另一个原因。
  • for (i in arr) 可能非常有用,但它也枚举了原型链,不幸的是有许多库将自己的函数添加到 Array 原型中。当然,您可以使用 hasOwnProperty 函数检查这一点,但我认为只是询问如何从数组中删除项目的人还不能完全掌握使用 'in' 的后果
【解决方案2】:

我认为您应该改写问题以更清楚。从您的示例中,如果position 属性与pinpoint 的属性匹配,则似乎可以从image.pinpoints 数组中删除多个元素。所以它将删除每个image.pinpoints[i].position == pinpoint.position,其中i0(image.pinpoints.length - 1)

由于您同时也在遍历数组,我不建议单独使用splice。而是先delete 每个索引,然后在第二遍中清理数组。

splicedelete 的工作方式不同,因为 delete 在数组中创建了一个洞并将已删除属性的值设置为 undefined。另一方面,splice 将删除该元素,就好像它从未存在过一样,并将其后所有元素的索引固定为连续。考虑这个例子:

> var a = [2,3,5,7,11]; // create an array of 5 elements
> undefined
> a[2] // see the value of the third element
> 5
> delete a[2] // delete the third element using "delete"
> true
> a // log contents of a
> [2, 3, undefined, 7, 11]
> a[2] // index 2 still exists with value "undefined" now
> undefined

splice 本身也是有问题的,如果你删除一个元素,该元素之后的所有索引都会上移一个,你会跳过检查下一个元素。考虑第二个例子:

> var a = [2,3,5,7,11]; // create array of 5 elements
> for(var i = 0; i < a.length; i++) { 
    if(a[i] == 3 || a[i] == 5) { // if it's 3 or 5, take it out
        a.splice(i, 1);
    }
}
> a
[2, 5, 7, 11]; // yikes, 5 still exists

在上面的示例中,5 仍然存在,因为我们从未检查过该值。当我们看到3 时,当前索引是1。拼接数组后,下一个元素 - 5 向上移动以占据它的位置并成为索引 1。由于此时我们已经完成了索引1,我们将简单地移动到下一个索引-2,它现在具有值7,并跳过5。一般来说,使用索引进行迭代并进行就地删除不是一个好习惯。

作为一种解决方案,我会创建一个新数组,并且只在其中插入不会被删除的属性。

$.fn.mapImage.deletePinpoint = function(image, pinpoint) {
    // will hold all objects that are not to be deleted
    var remainingPinpoints = [];

    for (var i = 0; i < image.pinpoints.length; i++) {
        // reverse condition
        if(image.pinpoints[i].position != pinpoint.position) {
            // add to new array
            remainingPinpoints.push(image.pinpoints[i]);
        }
    }

    // assign new array to pinpoints property
    image.pinpoints = remainingPinpoints;

    ...
}

【讨论】:

  • 虽然更多的是评论,但这个答案确实提出了一个非常重要的问题,即 OP 想要哪种行为
  • 关于您的编辑,您可以这样做: a.splice(i--,1);并且在拼接执行后i会递减
  • @Jonathan - 这会起作用,但是感觉很乱 :) 它使代码依赖于 for 循环,因为我们知道下一次迭代会将 i 的索引更新为当前值.如果第 0 个索引被删除,那么这意味着 i 将是 -1。如果稍后在删除后添加代码,很容易忘记i 现在指向一个无效的数组位置。很抱歉只在这方面提出更多问题,但这个问题并不像乍一看那样微不足道:)
  • 我认为如果你想根据它们的索引删除元素,你会在进入循环之前知道 99% 的情况下的索引。在这种情况下,您可以在进入循环之前调用 a.splice 函数。在删除基于位置属性的示例中,只要您立即使用 continue 关键字开始下一次迭代,使用 @Jonathan 建议是完全安全的。
【解决方案3】:

.splice 是 w3schools.com 提供的方法http://www.w3schools.com/jsref/jsref_splice.asp 要从索引为 x 的数组中删除一个元素,您需要 trees.splice(x,x+1); 这将删除 x 并在需要时返回它。

【讨论】:

    猜你喜欢
    • 2017-03-21
    • 1970-01-01
    • 2016-05-12
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-26
    相关资源
    最近更新 更多