17

我对mapping 创建的数组的结果感到困惑new

function returnsFourteen() {
    return 14;
}

var a = new Array(4);
> [undefined x 4] in Chrome, [, , , ,] in Firefox
a.map(returnsFourteen);
> [undefined x 4] in Chrome, [, , , ,] in Firefox

var b = [undefined, undefined, undefined, undefined];
> [undefined, undefined, undefined, undefined]
b.map(returnsFourteen);
> [14, 14, 14, 14]

我希望a.map(returnsFourteen)返回[14, 14, 14, 14](与 相同b.map(returnsFourteen),因为根据数组上的 MDN 页面

如果传递给 Array 构造函数的唯一参数是 0 到 2**32-1(含)之间的整数,则使用该数量的元素创建一个新的 JavaScript 数组。

我解释这意味着a应该有 4 个元素。

我在这里想念什么?

4

4 回答 4

15

当您像这样创建数组时:

var arr1 = new Array( 4 );

你得到一个长度为 的数组4,但它没有元素。这就是为什么map不转换数组的原因 - 数组没有要转换的元素。

另一方面,如果你这样做:

var arr2 = [ undefined, undefined, undefined, undefined ];

你得到一个长度也为 的数组4,但它确实有 4 个元素。

请注意没有元素和拥有值为 的元素之间的区别undefined。不幸的是,属性访问器表达式在这两种情况下都将评估为该undefined值,因此:

arr1[0] // undefined
arr2[0] // undefined

但是,有一种方法可以区分这两个数组:

'0' in arr1 // false
'0' in arr2 // true
于 2012-07-27T15:08:18.433 回答
10
var a = new Array(4);

这定义了一个显式长度为 4 但没有元素的新数组对象。

var b = [undefined, undefined, undefined, undefined];

这定义了一个隐含长度为 4 的新数组对象,其中包含 4 个元素,每个元素的值为undefined

文档

回调仅针对已分配值的数组索引调用;对于已被删除或从未被赋值的索引,它不会被调用。

对于 array a,没有元素被赋值,所以它什么也不做。

对于 array b,有四个元素被赋值(是的,undefined是一个值),所以它将所有四个元素映射到 number 14

于 2012-07-27T15:08:09.447 回答
5

new Array(len)创建一个空数组,并做一些不同于用undefined值填充它的事情:它将它的长度设置为len. 因此,它转换为以下代码:

var newArr = [];
newArr.length = len;

让我们玩得开心newArr(假设len = 4):

newArr.length; //4
newArr[1] === undefined; //true
newArr.hasOwnProperty(1); //false

这是因为虽然 4 项长,但它不包含这 4 项中的任何一项。想象一个空的子弹夹:它有空间可以容纳 20 颗子弹,但它不包含任何子弹。它们甚至没有设置为 value undefined,它们只是......未定义(这有点令人困惑。)

现在,Array.prototype.map愉快地沿着你的第一个数组走,唧唧喳喳,每次看到一个数组项,它就会调用一个函数。但是,当它沿着空弹夹走时,它没有看到任何子弹。当然,子弹有空间,但这并不意味着它们存在。在这里,没有值,因为映射到该值的键不存在。

undefined对于用值填充的第二个数组,undefined,键也是。or里面有东西,但是没有定义;但不在乎,只要它有一个键,它就会对任何值进行操作。b[1]b[3]Array.prototype.map

如需进一步检查规范:

于 2012-07-27T15:16:06.223 回答
1

关于console.log. 很简单,输出是,技术上是错误的。

让我们考虑这个例子:

var foo = new Array(4),
    bar = [undefined, undefined, undefined, undefined];

console.log( Object.getOwnPropertyNames(bar) );
console.log( Object.getOwnPropertyNames(foo) );

正如我们在结果中看到的,.getOwnPropertyNames函数返回

["length"]

对于foo数组/对象,但是

["length", "0", "1", "2", "3"]

对于bar数组/对象。

所以,只是在输出只有定义但没有实际属性分配的console.log输出时才会愚弄你。Arrays.length

于 2012-07-27T15:16:44.927 回答