Array.slice和Array()。slice之间的区别

时间:2020-03-06 14:35:48  来源:igfitidea点击:

我正在阅读John Resig的出色的高级javascript教程,但我并没有完全理解以下调用之间的区别:(请注意," arguments"是内置的javascript单词,并不完全是一个数组,因此使用Array.slice进行黑客入侵而不是简单地调用arguments.slice)

>>> arguments  
[3, 1, 2, 3]  
>>> Array.slice.call( arguments )  
3,1,2,3 0=3 1=1 2=2 3=3  
>>> Array.slice.call( arguments, 1 )  
[]
>>> Array().slice.call( arguments )  
3,1,2,3 0=3 1=1 2=2 3=3  
>>> Array().slice.call( arguments, 1 )  
1,2,3 0=1 1=2 2=3

基本上,我的误解归结为Array.slice和Array()。slice之间的区别。两者之间到底有什么区别,为什么Array.slice.call不能按预期运行? (这会返回除参数列表的第一个元素以外的所有元素)。

解决方案

数组只是一个函数,尽管是一个特殊的函数(用于初始化数组)。 Array.slice是Array原型中对slice()函数的引用。它只能在数组对象上调用,而不能在构造函数(即Array)本身上调用。 Array似乎表现得很特别,因为Array()返回一个空数组。对于非内置的Constructor函数,这似乎不起作用(必须使用new)。所以

Array().slice.call

是相同的

[].slice.call

出色地,

查看http://www.devguru.com/Technologies/ecmascript/quickref/slice.html

Array()。slice是数组类中的一个函数(构造函数),不能用作数据成员。如果我们不想使用'()',则需要在数组上调用它。即arguments.slice(1)

我的猜测是Array是原型,而Array()是实际的数组对象。根据JavaScript的解释,直接调用内置对象类型的原型方法可能有效,也可能无效。我不认为规范说它必须工作,只是在实例化对象上调用它就可以工作。

我相信Array是类型,而Array()是构造函数。

在FireBug中乱七八糟:

>>> Array === Array()
false

>>> Array.constructor
Function()

>>> Array().constructor
Array()

不完全的。

观察调用String.substring.call(" foo",1)和String()。substring.call(" foo",2)时发生的情况:

>>> String.substring.call("foo", 1)
"1"

>>> String().substring.call("foo", 1)
"oo"

Array.slice既未正确引用添加到Array原型的slice函数,也未正确引用添加到任何实例化Array实例(例如Array()或者[])的slice函数。

Array.slice甚至根本不是null的事实是对象(/函数/构造函数)本身的错误实现。尝试在IE中运行等效代码,我们将得到一个错误,即Array.slice为null。

这就是Array.slice行为不正确的原因(String.substring也不如此)。

证明(以下是基于slice()的定义,绝对不应该期望的东西,就像上面的substring()一样):

>>> Array.slice.call([1,2], [3,4])
3,4

现在,如果我们在实例化对象或者Array原型上正确调用slice(),我们将获得期望的结果:

>>> Array.prototype.slice.call([4,5], 1)
[5]
>>> Array().slice.call([4,5], 1)
[5]

更多证据...

>>> Array.prototype.slice == Array().slice
true
>>> Array.slice == Array().slice
false

由于未提供上下文参数,因此在提供的示例中如何对slice.call()进行任何调用? slice是否实现了它自己的调用方法,从而覆盖了JavaScript的调用方法?调用和应用方法将第一个参数作为对象,以指定要应用于调用的上下文(此)对象。