我可以确定array.slice()将始终与array.slice(0)相同吗?

时间:2013-08-12 06:35:26

标签: javascript

我总是使用没有参数的.slice()方法来制作JavaScript Array的副本。这在我尝试的每个浏览器和JavaScript环境中都可以正常工作:它与.slice(0)的处理方式相同。

这只是一个风格问题,但对我来说,省略 start 参数完全使我们更清楚地知道我们没有采用数组的任何特殊子切片但是需要整个副本的事情。

但是,MDNMSDN都表示array.slice()的第一个参数是必需。只有第二个参数是可选的。其他在线来源,例如TutorialsPointW3Schools也说同样的话。 (不,我不推荐W3Schools!只是指出他们在这个问题上同意MDN和MSDN。)

我刚刚幸运吗?是否存在array.slice()不起作用的浏览器或其他JavaScript环境?

1 个答案:

答案 0 :(得分:9)

所有这些在线参考都是错误的。

至少如果我们谈论的是标准兼容的浏览器和运行时。

ECMA-262 standard要求任何符合要求的实施方案将array.slice()array.slice(0)完全相同。

以下是我们对此的了解。

首先我们看一下Section 15.4.4.10,“Array.prototype.slice(start,end)”:

  

slice方法有两个参数, start end ,并从元素 start 最多但不包括元素 end (或者如果 end undefined,则通过数组末尾)...

这是什么?甚至没有提到 end 是可选的。是否需要开始结束

是的,他们是。但我们需要到别处去了解这意味着什么。

Section 15,“标准内置ECMAScript对象”说(第四段):

  

除非在特定函数的描述中另有规定,否则如果给定本节中描述的函数或构造函数的参数少于指定函数所需的参数,则函数或构造函数的行为应与给予足够的额外函数完全相同参数,每个这样的参数都是undefined值。

这与指定其他方法的方式一致。例如,我们知道array.sort()的compare函数参数是可选的,但是Section 15.4.4.11“Array.prototype.sort(comparefn)”没有说明 comparefn 参数是可选的。它只描述 comparefn 是否为undefined时要执行的操作。

现在我们知道array.slice()被解释为array.slice(undefined,undefined)。然后,继续Section 15.4.4.10,我们找到相关的步骤:

  

5。让 relativeStart 为ToInteger( start )。

Section 9.4中描述了

ToInteger ,其中前两个步骤是相关的:

  

1。设 number 是在输入参数上调用ToNumber的结果   2。如果号码为NaN,请返回+0

Section 9.3中找到

ToNumber ,其中表中的第一个条目表示当其参数​​类型未定义时,结果为NaN

因此,array.slice()缺少的第一个参数被视为undefined,该值将传递给ToNumber,返回NaN。这会导致ToInteger返回0(或+0,因为他们在此处调用它),这是array.slice()使用的值。

因此,array.slice()array.slice(0)相同。如果实现不以这种方式对待它,则它不符合ECMA-262标准。

当然,这是标准,然后就是现实世界。

如果我们对.slice() second 参数进行同样的分析,我们会得出结论,所有这些都应该相同(在其他类似的变体中):< / p>

array.slice()
array.slice( 0 )
array.slice( undefined )
array.slice( 0, undefined )
array.slice( undefined, undefined )

然而,正如@ Pumbaa80在评论中指出的那样,最后两个版本在IE8中不起作用(也不在IE7中)!

但至少我关注的简单array.slice()案例在这些旧浏览器中工作,并且应该继续在遵循该标准的任何浏览器或运行时中工作。