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

Mic*_*ary 4 javascript

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

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

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

我刚刚幸运吗?可能有浏览器或其他JavaScript环境array.slice()不起作用?

Mic*_*ary 9

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

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

ECMA-262标准要求任何符合标准的实现来治疗array.slice()相同到array.slice(0).

以下是我们对此的了解.

首先我们看一下第15.4.4.10节 "Array.prototype.slice(start,end)":

slice方法接受两个参数,startend,并返回一个数组,其中包含从元素start到(但不包括)元素end的数组元素(如果end为end,则返回数组末尾undefined)...

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

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

第15节 "标准内置ECMAScript对象"(第4段)说:

除非在特定函数的描述中另有规定,否则如果给定本节中描述的函数或构造函数的参数少于指定函数所需的参数,则函数或构造函数的行为应完全像给出足够的附加参数一样这样的论证就是undefined价值.

这与指定其他方法的方式一致.例如,我们知道compare函数参数array.sort()是可选的,但是第15.4.4.11节 "Array.prototype.sort(comparefn)"没有说明comparefn参数是可选的.它只描述了comparefn是否存在时要做什么undefined.

所以现在我们知道这array.slice()被解释为array.slice(undefined,undefined).然后,继续第15.4.4.10节,我们找到相关步骤:

5.让relativeStart成为ToInteger(开始).

ToInteger9.4节中描述,其中前两个步骤是相关的:

1.设number是在输入参数上调用ToNumber的结果.
2.如果是NaN,则返回+0.

ToNumber可以在9.3节中找到,其中表中的第一个条目表示当其Argument Type为Undefined时,结果为NaN.

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

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

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

如果我们对第二个参数进行同样的分析.slice(),我们将得出结论,所有这些都应该相同(在其他类似的变化中):

array.slice()
array.slice( 0 )
array.slice( undefined )
array.slice( 0, undefined )
array.slice( undefined, undefined )
Run Code Online (Sandbox Code Playgroud)

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

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

  • 非常好,但严格来说这并不能回答你的问题.以IE8为例,其中(根据MSDN)抛出`slice(0,undefined)`而`slice(0)没有问题` (3认同)