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