我总是使用没有参数的.slice()
方法来制作JavaScript Array
的副本。这在我尝试的每个浏览器和JavaScript环境中都可以正常工作:它与.slice(0)
的处理方式相同。
这只是一个风格问题,但对我来说,省略 start 参数完全使我们更清楚地知道我们没有采用数组的任何特殊子切片但是需要整个副本的事情。
但是,MDN和MSDN都表示array.slice()
的第一个参数是必需。只有第二个参数是可选的。其他在线来源,例如TutorialsPoint和W3Schools也说同样的话。 (不,我不推荐W3Schools!只是指出他们在这个问题上同意MDN和MSDN。)
我刚刚幸运吗?是否存在array.slice()
不起作用的浏览器或其他JavaScript环境?
答案 0 :(得分:9)
所有这些在线参考都是错误的。
至少如果我们谈论的是标准兼容的浏览器和运行时。
ECMA-262 standard要求任何符合要求的实施方案将array.slice()
与array.slice(0)
完全相同。
以下是我们对此的了解。
首先我们看一下Section 15.4.4.10,“Array.prototype.slice(start,end)”:
这是什么?甚至没有提到 end 是可选的。是否需要开始和结束?
slice
方法有两个参数, start 和 end ,并从元素 start 返回包含数组元素的数组最多但不包括元素 end (或者如果 end 是undefined
,则通过数组末尾)...
是的,他们是。但我们需要到别处去了解这意味着什么。
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,我们找到相关的步骤:
Section 9.4中描述了5。让 relativeStart 为ToInteger( start )。
ToInteger ,其中前两个步骤是相关的:
在Section 9.3中找到1。设 number 是在输入参数上调用ToNumber的结果 2。如果号码为
NaN
,请返回+0
。
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()
案例在这些旧浏览器中工作,并且应该继续在遵循该标准的任何浏览器或运行时中工作。