Javascript数组长度修改的含义

时间:2017-04-30 23:17:21

标签: javascript arrays

我在尝试扩展Array.prototype时注意到了一些事情。我本质上想写一个允许删除数组中最后一项的方法:

Array.prototype.removeLast = function() {
    delete this[this.length - 1];
};

这不会产生我预期的结果:

>>> var arr = [ 1, 2, 3 ];
[ 1, 2, 3 ]
>>> arr.removeLast();
undefined
>>> arr
[ 1, 2, undefined ]

所以我尝试了另一种方法:

Array.prototype.removeLast = function() {
    this.length--;
};

我得到了预期的结果。

>>> var arr = [ 1, 2, 3 ];
[ 1, 2, 3 ]
>>> arr.removeLast();
undefined
>>> arr
[ 1, 2 ]

问题

1)为什么没有像对象密钥删除那样运行数组索引删除? (对于数组,引用似乎仍然存在,但只引用undefined。对于对象,引用似乎完全被删除。)

2)this.length--方法安全吗?它可能导致内存泄漏,或者是 更改对象的length属性也会导致检查运行并删除数组中任何被遗忘的索引?

3)前两个问题中的任何一个问题的答案是否因实施而异?

4)什么是removeLast的良好实施?

谢谢!

1 个答案:

答案 0 :(得分:1)

正如MDN针对deleting array elements所解释的那样:

  

删除数组元素时,数组长度不受影响。即使您删除了数组的最后一个元素,这也成立。

     

当delete运算符删除数组元素时,该元素不再在数组中。在以下示例中,将使用delete删除树[3]。

对于您的数组,您正在尝试删除索引(使用它,它的值),这是使用delete运算符执行的,但不是您想象的那样。索引/值被删除,但JavaScript引擎如何组装数组并操纵其属性(例如,length)将不会按您的想法执行。它仍会显示缺少的索引w / undefined,这就是你所看到的。

示范

为了更好地演示,如果Object.keys( your_array ),您将看到您删除的数组的索引不存在;同样,如果您执行Object.values( your_array ),您会看到undefined未返回。对于所有意图和目的,您删除了属性(索引)及其关联值。

其他考虑因素

您可以考虑使用use splicepop(如果是最后一个索引)来删除数组的最后一个元素;然而,这并非没有认识到它们自身的影响:

  • splice将重新排序数组,将值转换为新索引;这与delete不同,后者将所有内容保留在原始索引

  • pop只会删除数组中的最后一项/索引

  • splicepop都会更新数组的length属性

delete vs splice vs pop

的示例

console.log('\nDELETE');
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];
console.log('array: ', trees);
console.log('keys: ', Object.keys(trees) );
console.log('values: ', Object.values(trees) );
console.log('length: ', trees.length );
trees.forEach(val=>console.log(val)); // notice no undefined


console.log('\nPOP');
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.pop();
console.log('array: ', trees);
console.log('keys: ', Object.keys(trees) );
console.log('values: ', Object.values(trees) );
console.log('length: ', trees.length );
trees.forEach(val=>console.log(val));


console.log('\nSPLICE');
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);
console.log('array: ', trees);
console.log('keys: ', Object.keys(trees) );
console.log('values: ', Object.values(trees) );
console.log('length: ', trees.length );
trees.forEach(val=>console.log(val));

问题

  

1)为什么数组索引删除操作不像对象密钥删除? (对于数组,引用似乎仍然存在,但只是引用未定义。对于对象,引用似乎完全被删除。)

是。

  

2)this.length--方法安全吗?它是否会导致内存泄漏,或者更改对象的长度属性是否也会导致检查运行并删除数组中任何被遗忘的索引?

最好不要自己操作和管理长度。从历史上看,不同的浏览器对长度操作的响应方式不同。

我最近几年看到length操作的唯一一次是清除一个数组(即arr.length = 0)。这比将数组分配给新的空数组(即arr = [])更适合,因为数组可能包含某些不应丢失或重新构造的属性。

  

3)前两个问题中的任何一个问题的答案是否因实施而异?

  

4)removeLast的优秀实现是什么?

arr.pop()arr.splice(-1,1)