【发布时间】:2019-11-27 10:49:57
【问题描述】:
我一直在尝试实现一种方法,该方法将数组和索引作为输入,将给定数组的最后一个元素复制到给定索引处的条目中,然后截断最后一个元素(即设置数组短一)。
以下是我为这项任务提供的建议功能:
function swapWithLastAndRemove(array, index) {
array[index] = array.pop();
}
然后我测试了这个函数以确保它适用于任何给定的索引:
for (let index = 0; index < 5; index++) {
var array = [0, 1, 2, 3, 4];
swapWithLastAndRemove(array, index);
console.log(array);
}
我发现它对除最后一个索引之外的所有索引都正常工作:
[ 4, 1, 2, 3 ]
[ 0, 4, 2, 3 ]
[ 0, 1, 4, 3 ]
[ 0, 1, 2, 4 ]
[ 0, 1, 2, 3, 4 ]
换句话说,对于最后一个元素,它会将其从数组中弹出,然后将其重写到数组中。
让我印象深刻的是,这一行:
array[index] = array.pop();
在最后一个元素上执行时相当于这一行:
array[array.length - 1] = array.pop();
不可能导致array 的内容等于[ 0, 1, 2, 3, 4 ]。
在我看来,这里有两种选择:
- 语句
array.pop()在计算表达式array.length - 1之前执行 - 语句
array.pop()在表达式array.length - 1被计算后执行
在第一种情况下,数组的内容会发生如下变化:
[ 0, 1, 2, 3, 4 ] // initial state[ 0, 1, 2, 3 ] // after popping 4[ 0, 1, 2, 4 ] // after assignment
在第二种情况下,它应该触发了某种内存访问冲突,因为当数组的长度仅为 4 时,将尝试写入数组中的第 5 个条目 (array[4])条目。
我知道 NodeJS 可能正在应用一些内存管理方案,它会以某种方式允许它在没有“数组索引超出范围”异常的情况下完成,但我仍然不明白为什么它会让这个操作“逃脱它”,以及为什么结果是这样的。
array[array.length - 1] = array.pop() 行可能是未定义的行为吗?
JavaScript 中是否存在未定义的行为?
【问题讨论】:
-
取最后一个索引想要什么结果?
-
"在第二种情况下,它应该触发了某种内存访问冲突," 为什么?
arr = []; arr[42] = "hello"不是问题。 JS 中的数组是动态的,并不真正对应于大多数其他语言中的数组,而是更像 Java 中的 ArrayList -
不,在 JS wrt 评估顺序中没有未定义的行为 - 它总是从左到右。
arrray.length-1表达式在array.pop()调用之前评估
标签: javascript arrays node.js