2

有人会认为在 JavaScript: var array = [1,2,undefined,4]; 中与:

var array = [1,2];
array.length = 3;
array.push(4);

但事实并非如此。这段代码显示了它:

var array1 = [1,2];
array1.length = 3;
array1.push(4);

var array2 = [1,2,undefined,4];

traverseArray(array1);
traverseArray(array2);

function traverseArray(array) {
  console.log("trying: " + array);
  console.log("reduce:");
  array.reduce(function(prev, current, index, array) {
    if(current === undefined) {
      console.log("Found undefined");
    }
    console.log(index+": " +current);
  }, undefined);

  console.log("for loop:")
  for(var i=0;i < array.length;i++) {
    var current = array[i];
    console.log(i+": " +current);
  }
  console.log();
}

输出:

trying: 1,2,,4
reduce:
0: 1
1: 2
3: 4
for loop:
0: 1
1: 2
2: undefined
3: 4

trying: 1,2,,4
reduce:
0: 1
1: 2
Found undefined
2: undefined
3: 4
for loop:
0: 1
1: 2
2: undefined
3: 4

为什么 array1 中的 undefined 与 array2 中的 undefined 不一样,为什么 for 循环的行为相同而 reduce 不一样?

4

2 回答 2

4

array1具有三个以数字命名的属性:013.

array2有四个以数字命名的属性:0123. 名为的属性的值2恰好是undefined

当你向一个对象询问它没有的属性的值时,结果是undefined.

for循环中,您向每个数组询问其名为012和的属性的值3。对于array1,命名的属性2不存在,因此属性访问产生undefined。对于array2,该属性确实存在,但它的值实际上 undefined,因此您会得到相同的结果。

另一方面,reduce仅对实际存在的属性进行操作。根据 ECMAScript 规范,这是reduce使用计数器循环数组的方式k

  1. 重复,而k < len
    • Pk为 ToString( k )。
    • kPresent成为使用参数Pk调用O的 [[HasProperty]] 内部方法的结果。
    • 如果kPresent为真,那么... [使用索引 k 处的值进行 reduce 调用]

因此,我们可以看到只有通过 [[HasProperty]] 检查才使用索引。array1没有名为 的属性2,因此会跳过该索引。

于 2015-02-20T18:59:14.560 回答
3

apsillers nailed it in the comments . . . the difference is that in array2 you have actually assigned an undefined value to the 3rd element in the array (i.e., at index 2), where as, in array1, you have two elements initially, change the length property, and then add a third element in the forth position.

Here are the relevent sections from MDN that explains why the distinction is important:

  • From the page on Array.length:

When you extend an array by changing its length property, the number of actual elements does not increase; for example, if you set length to 3 when it is currently 2, the array still contains only 2 elements. Thus, the length property says nothing about the number of defined values in the array.

  • From the page on Array.push():

The push method relies on a length property to determine where to start inserting the given values.

The key here, is really that the length property is really, simple a property that is in no way inherantly tied to the contents of the array. It is simply because the various methods of Array also happen to maintain that property, as they "do their work", that I behaves as if it is.

So, as a result, in array2, the code is actually reporting back the undefined value that you assigned to array2[2], whereas, with array1, the code is interpreting the absence of a value at array1[2] as undefined.

于 2015-02-20T18:58:51.277 回答