Javascript 对使用“new”创建的数组上的“map”行为感到困惑`
我被Javascript 对使用“new”创建的数组上的“map”行为感到困惑`,javascript,arrays,map,new-operator,Javascript,Arrays,Map,New Operator,我被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, un
map
ping使用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)
,因为根据
如果传递给数组构造函数的唯一参数是整数
在0和2**32-1(含)之间,将创建一个新的JavaScript数组
有那么多的元素
var b = [undefined, undefined, undefined, undefined];
我认为这意味着a
应该有4个元素
我错过了什么
var a = new Array(4);
这将定义一个显式长度为4但没有元素的新数组对象
var b = [undefined, undefined, undefined, undefined];
这将定义一个隐式长度为4的新数组对象,其中包含4个元素,每个元素的值未定义
从:
仅对已分配的数组的索引调用回调
值;对于已删除的索引或
从未分配过值
对于数组a
,没有已赋值的元素,因此它不执行任何操作
对于数组
b
,有四个元素被赋值(是的,未定义的
是一个值),因此当您创建这样的数组时,它会将所有四个元素映射到编号14
:
var arr1 = new Array( 4 );
您得到的数组长度为4
,但没有元素。这就是为什么map
不转换数组-数组没有要转换的元素
另一方面,如果您这样做:
var arr2 = [ undefined, undefined, undefined, undefined ];
您得到的和数组的长度也为4
,但它有4个元素
var b = [undefined, undefined, undefined, undefined];
请注意没有元素和具有值为未定义
的元素之间的区别。不幸的是,在这两种情况下,属性访问器表达式的计算结果都是未定义
值,因此:
arr1[0] // undefined
arr2[0] // undefined
但是,有一种方法可以区分这两种阵列:
'0' in arr1 // false
'0' in arr2 // true
newarray(len)
创建一个空数组,并执行与用未定义的值填充数组不同的操作:它将其长度设置为len
。因此,它转换为以下代码:
var newArr = [];
newArr.length = len;
让我们来享受一下newArr
(假设len=4
):
这是因为虽然有4个项目长,但它不包含这4个项目中的任何一个。想象一下一个空的子弹夹:它有空间容纳(比如)20个子弹,但它不包含任何子弹。它们甚至没有设置为值undefined
,它们只是…undefined(这有点让人困惑)
现在,Array.prototype.map
愉快地沿着你的第一个数组走着,唧唧喳喳,吹着口哨,每次它看到一个数组项,它都会调用一个函数。但是,当它沿着空的子弹夹走着时,它看不到子弹。当然,子弹是有空间的,但这并不意味着它们的存在。在这里,没有价值,因为映射到该值的ch不存在
对于第二个数组,它填充了未定义的
值,值是未定义的
,键也是如此。在b[1]
或b[3]
中有一些内容,但这些内容没有定义;但是array.prototype.map
并不重要,只要有键,它将对任何值进行操作
对于规范中的进一步检查:
新阵列(len)
:
Array.prototype.map
:(请密切注意步骤8.b)
关于console.log
行为的另一个答案。非常简单,输出是sugar,技术上是错误的
让我们考虑这个例子:
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"]
用于条
数组/对象
因此,console.log
只是在输出array
时愚弄了你,这些数组只有一个定义的.length
,但没有实际的属性分配。.map()
的工作方式不是破坏性的,试着将结果分配回a
奇怪的是,如果你这样做console.log(a,b)在任何映射之前,它返回:[undefined×4][undefined,undefined,undefined,undefined]
(在Chrome中)@尼尔:那只是控制台
糖。实际上,我们有一个数组
,长度为4@jAndy呃,他们应该记录同样的事情,不是吗?@Matt:那么,在我看来,这不是一个好问题。你在文档中指出了一个有争议的段落,这很好,但也可以解决,然后问题就不存在了不再存在。这更适合作为某种bug报告或其他地方的讨论(例如:)。那么MDN文档中的引用--一个新的JavaScript数组是用那个数量的元素创建的,是错误的,还是我误解了它?对我来说,这似乎意味着实际上有带值的元素。@MattFenwick文档是正确的。未定义的元素和元素之间有一个重要的区别如果MDN的值未定义
@jbabey,但是新数组(4)
会创建一个没有元素的数组,因此MDN文档是不正确的……根据MDN,该数组将有4个元素。@jbabey我不同意。数组元素是一个属性,属性名称是数组索引(非负整数,或表示此类数字的字符串:'1'
,'2'
,'3'
等)。未指定将任何元素添加到新创建的数组中。此外,当使用此类数组调用对象.getOwnPropertyNames
时,结果将包含'length'
字符串,但不包含数组索引。因此,数组不包含任何元素,而仅包含'length'
属性。以查看@jAndy的答案了解详细信息。此外,大多数conso