从javascript数组中删除元素后,数组的长度不会改变。

13

我想将一个数组的值复制到另一个数组中,但不破坏与该数组相关联的链接,换句话说,我不能只将新数组分配给这个值,因此我无法使用像slice()或concat()这样的方法。 下面是执行此操作的函数的代码:

 self.updateBreadcrumbs = function (newBreadcrumbs) {
            var old_length = self.breadcrumbs.length;
            var new_length =newBreadcrumbs.length;
            var j = new_length > old_length ? new_length: old_length;

            for (var i = 0; i < j; i++) {
                if(old_length < i+1){
                    self.breadcrumbs.push(newBreadcrumbs[i]);
                    continue;
                }
                if(new_length < i+1){
                    delete self.breadcrumbs[i];
                    continue;
                }
                if (self.breadcrumbs[i].title !== newBreadcrumbs[i].title) {
                    self.breadcrumbs[i] = newBreadcrumbs[i];
                }

            }
        }

我的问题是,如果我从数组中删除了某些内容,那么数组的长度不会改变。

附言:如果您知道更简单的方法来解决这个问题,我完全可以接受建议。


2
删除一个元素不应该改变数组的长度。 - Pointy
1
@georg 1,我有一个Angular服务,可以在控制器之间共享此数组,如果我重新分配该数组,则控制器内部的链接将会断开。 - Dmitrij Kostyushko
即使 delete 改变了数组的长度(实际上它并没有),你也没有重新计算 old_length,所以当然不会改变。 - joeytwiddle
如果您只想使用ES6的"rest语法"和Array.prototype.splice在一行中删除和插入,以覆盖newBreadcrumbs中的项目与self.breadcrumbs的项目,则可以使用以下代码:newBreadcrumbs.splice(0, newBreadcrumbs.length, ...self.breadcrumbs); - joeytwiddle
或者不要将数组传递到函数中,让函数返回一个数组:var newBreadcrumbs = self.breadcrumbs.slice(0); return newBreadcrumbs; - joeytwiddle
显示剩余6条评论
5个回答

30

删除数组中的元素不能改变数组的长度。

但是可以使用splice来更改它,例如:

var arr=[1,2,3,4,5]; //length 5
arr.splice(0,1); //length 4
与常见的看法不同,delete运算符与直接释放内存无关。 delete仅对对象属性有效,在数组长度上没有影响。

splice()方法通过删除现有元素和/或添加新元素来更改数组的内容。

有关splice的更多信息


但是 slice() 将返回新数组,不是吗?如果是这种情况,它在这种情况下不合适。 - Dmitrij Kostyushko
2
它是splice而不是slice。 - Vicky Gonsalves

6
一个数组对象的属性 length 是由它的方法维护的,而不是对象本身固有的特性。因此,如果你对它执行的操作不是 Array 自己的方法之一,它就不会更新 length 属性。在这种情况下,你需要使用的是 splice 方法(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)。
有趣的是,您可以通过直接更改其长度来改变数组的组成部分。例如,如果您有一个包含6个元素的数组,并将其 length 属性更改为5(即array.length = 5;),它将不再将第6个元素视为数组的一部分。
更多关于 length 属性的内容,请参见:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length

2
除了其原型方法之外,数组与简单对象并没有太大的区别。不同之处在于长度属性具有特殊的setter方法,并且添加新属性的方式也不同。 如果向对象添加属性,则会测试其名称是否为数字值以及此值是否>=当前数组长度。如果是,则更新内部长度。 如果设置了长度,则会检查新值是否小于旧值,如果是,则将删除所有拥有数值属性名称且>=新长度的自有属性。
如果从数组中删除索引元素,则它将被删除(访问此索引后来将返回未定义,就像任何不存在的属性一样)。它不会更改数组长度,增加数组长度也不会为添加的索引位置创建任何属性(稀疏数组)。使用[]或new Aray [10000]都将创建具有完全相同内存占用的数组。只是长度属性具有不同的初始值。
这与其他语言中的数组完全不同,在其他语言中,大小为n的数组将为元素保留n个存储空间(指向对象或本地值类型的指针)。因此,在其他语言中,创建具有给定大小并填充它的数组比创建一个空数组并添加值要快(在这种情况下,每次必须分配更大的连续空间,并且必须将数组复制到此更大的内存位置,然后再添加元素)。另一方面,在JS数组中访问元素要慢一些(因为它们只是具有命名属性的属性,必须首先在属性列表中找到它们),而在其他语言中,元素位于其给定的固定位置。

这里只是想指出,具有固定长度的数组是通过括号new Array(1000)创建的,其中数字1000是构造函数的参数。 - Alwin Kesler

0

如果您使用数组,这个答案将无法帮助您。

如果您仍然需要按键删除项目并且可以使用对象:

$o = {'blue' : '', 'apple' : '', 'red' : ''};

console.log(Object.keys($o).length); // will output 3 
delete $o['apple'];
console.log(Object.keys($o).length); // will output 2

0
let arr = ['qwe', 1, null]
delete arr[1]      // true
arr.length         // 3 if you do not like such result, use
arr.flat().length  // 2, ok?
arr                // ['qwe', empty, null]

但是如果你的数组包含其他数组,这种方法就不太适用了。


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