Javascript Array.apply(null,数组(x))和Array(x)之间的差异

Javascript Array.apply(null,数组(x))和Array(x)之间的差异,javascript,Javascript,以下两者之间的具体区别是什么: Array(3) // and Array.apply(null, Array(3) ) 第一个返回[undefined x 3],而第二个返回[undefined,undefined,undefined]。第二个是可以通过数组.prototype.functions链接的,比如.map,但第一个不是。为什么?有一个区别,一个非常重要的区别 数组构造函数要么接受一个数字,给出数组的长度,然后创建一个索引为“空”的数组,或者更准确地说,设置了长度,但数组实际上不包

以下两者之间的具体区别是什么:

Array(3)
// and
Array.apply(null, Array(3) )

第一个返回
[undefined x 3]
,而第二个返回
[undefined,undefined,undefined]
。第二个是可以通过
数组.prototype.functions
链接的,比如
.map
,但第一个不是。为什么?

有一个区别,一个非常重要的区别

数组
构造函数要么接受一个数字,给出数组的长度,然后创建一个索引为“空”的数组,或者更准确地说,设置了长度,但数组实际上不包含任何内容

Array(3); // creates [], with a length of 3
当使用数字作为唯一参数调用数组构造函数时,将创建一个空数组,该数组不能使用常规数组方法进行迭代

。。。数组构造函数接受多个参数,而创建数组时,每个参数都是数组中的一个值

Array(1,2,3); // creates an array [1,2,3] etc.
当你称之为

Array.apply(null, Array(3) )
它变得更有趣了

apply
接受
this
值作为第一个参数,由于它在这里没有用处,所以将其设置为
null

有趣的部分是第二个参数,其中传入了一个空数组。
apply
接受数组时,就像调用

Array(undefined, undefined, undefined);
这将创建一个包含三个索引的数组,这三个索引不是空的,但其值实际设置为
未定义的
,这就是它可以被迭代的原因

TL;DR
主要区别在于
Array(3)
创建了一个包含三个空索引的数组。事实上,它们并不存在,数组的长度只有
3

使用
apply
将带有空索引的数组传递给数组构造函数与执行
array(未定义、未定义、未定义)相同
,它创建了一个包含三个
未定义
索引的数组,
未定义
实际上是一个值,因此它不像第一个示例中那样为空


map()
这样的数组方法只能对实际值进行迭代,而不能对空索引进行迭代。

因为第一个数组不具有有序属性
arr[0]==未定义的属性,而第二个数组具有。像forEach和map这样的数组函数将从0迭代到数组的长度-1,第一个数组的属性缺少顺序是一个问题。第二个版本生成具有正确顺序的数组,即

arr = Array.apply(null, Array(3));
arr[0] === undefined //true
arr[1] === undefined //true
//etc.
你注意到的第一个版本没有。另外,向第一个版本中添加
新的
也无法使其工作。

map()
API不会迭代完全未初始化的数组元素。当您使用
新数组(n)
构造函数创建一个新数组时,您将得到一个具有所要求的
.length
的数组,但其中不存在元素,这些元素将被
.map()
等方法跳过

表达式
Array.apply(null,Array(9))
undefined
显式填充新创建的数组实例,但这已经足够了。诀窍在于
操作符中的
是否会报告数组在给定索引处包含元素。即:

var a = new Array(9);
alert(2 in a); // alerts "false"
这是因为数组中的
2
位置确实没有元素。但是:

var a = Array.apply(null, Array(9));
alert(2 in a); // alerts "true"

对数组构造函数的外部调用将显式填充元素。

这是apply如何工作的工件。当您这样做时:

new Array(9)
将创建一个长度为9的空数组。map不会访问不存在的成员,所以什么也不访问。但是,使用将数组转换为列表,以便将以前的空数组转换为参数列表,如:

[undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined];
传递给数组以创建一个包含9个成员的数组,所有成员的值均为undefined。所以现在map将访问他们所有人

顺便说一句,ECMAScript 2015已对此进行了测试(另请参阅),因此您可以执行以下操作:

Array(9).fill(0);

在第一种情况下,您有一个操作

阵列(3)

它将创建一个包含三个空插槽的阵列。不是一个包含三个未定义值的数组,而是一个完全为空的数组

在第二个案件中

Array.apply(null,数组(3))

我们可以将其推广到三个业务:

  • 第一:数组(3)-你得到一个有3个空插槽的数组

  • 第二:数组(3)按Function.prototype.apply()函数传播到传递给数组()函数的3个参数。在此阶段,给定数组中的3个空插槽通过apply()转换为3个未定义的值(看起来,如果apply()看到一个空插槽,它会自动将其转换为任何稀疏数组中的未定义)

  • 第三:我们得到一个数组(未定义,未定义,未定义)。这将为我们提供一个包含3个未定义(非空)值的数组

因为现在有3个未定义但不是空的插槽,所以可以将它们与map()函数一起使用

请注意,不仅Function.prototype.apply()具有通过这种方式分解数组的行为。您也可以在ECMAScript 6中通过“…”扩展运算符执行此操作

Array(...new Array(3));
这还将返回一个包含3个未定义和可映射插槽的数组

在这里,我将给出更详细的解释。
谢谢你的回答,我不确定每一个时隙中的值与未定义的值不一样,因为索引到任何给定的位置都返回未定义的。@ MbS88考虑数组中的代码>0(9);false
@mb_s88 answer扩展了一点
函数。prototype.apply
也不关心
argArray
是否为真数组,只要它是可读对象,
Array.apply(null,{length:“2.5”});//[未定义,未定义]
数组。应用(null,数组(9))
不是
新数组(9)
。它将
数组(9)
扩展为
数组()
作为九个参数。即使它能起作用,也几乎是错误的。例如,您可以
newarray(1e7)
但不能
Array.apply(null,Array(1e7))
。Relate