我知道它用于使参数成为真实的数组,但是我不明白使用时会发生什么 Array.prototype.slice.call(arguments)
Array.prototype.slice.call()如何工作?
It uses the slice
method arrays have and calls it with its this
being the arguments
object. This means it calls it as if you did arguments.slice()
assuming arguments
had such a method.
Creating a slice without any arguments will simply take all elements - so it simply copies the elements from arguments
to an array.
Array.prototype.slice.call(arguments) is the old-fashioned way to convert an arguments into an array.
In ECMAScript 2015, you can use Array.from or the spread operator:
let args = Array.from(arguments);
let args = [...arguments];
Dont forget, that a low-level basics of this behaviour is the type-casting that integrated in JS-engine entirely.
Slice just takes object (thanks to existing arguments.length property) and returns array-object casted after doing all operations on that.
The same logics you can test if you try to treat String-method with an INT-value:
String.prototype.bold.call(11); // returns "<b>11</b>"
And that explains statement above.
该arguments
对象实际上不是Array的实例,并且不具有任何Array方法。因此,arguments.slice(...)
将不会起作用,因为arguments对象没有slice方法。
数组确实具有此方法,并且由于arguments
对象与数组非常相似,因此两者是兼容的。这意味着我们可以将数组方法与arguments对象一起使用。而且由于数组方法是在考虑数组的基础上构建的,因此它们将返回数组而不是其他参数对象。
那为什么要使用Array.prototype
呢?的Array
是,我们创建从(新阵列的对象new Array()
),而这些新的阵列被传递的方法和属性,像切片。这些方法存储在[Class].prototype
对象中。因此,出于效率的考虑,我们不必直接通过原型直接获取切片方法,而不必通过(new Array()).slice.call()
or 来访问slice方法[].slice.call()
。这样一来,我们不必初始化新的数组。
但是为什么我们必须首先这样做呢?好了,正如您所说,它将参数对象转换为Array实例。但是,我们使用slice的原因更多的是“ hack”。您猜到了,slice方法将获取一个数组的切片,并将该切片作为新数组返回。不向其传递任何参数(以arguments对象作为上下文除外)会使slice方法获取传递的“数组”(在本例中为arguments对象)的完整块,并将其作为新数组返回。
通常,打电话
var b = a.slice();
将数组复制a
到中b
。但是,我们不能
var a = arguments.slice();
因为arguments
它不是一个真正的数组,也没有slice
作为方法。Array.prototype.slice
是slice
数组的函数,并call
以this
设置运行函数arguments
。
Its because, as MDN notes
The arguments object is not an array. It is similar to an array, but does not have any array properties except length. For example, it does not have the pop method. However it can be converted to a real array:
Here we are calling slice
on the native object Array
and not on its implementation and thats why the extra .prototype
var args = Array.prototype.slice.call(arguments);
首先,您应该阅读JavaScript中函数调用的工作方式。我怀疑仅此一项就足以回答您的问题。但是,这里是正在发生的事情的摘要:
Array.prototype.slice
提取方法从的原型。但是直接调用它是行不通的,因为它是方法(不是函数),因此需要上下文(调用对象),否则会抛出。slice
Array
this
Uncaught TypeError: Array.prototype.slice called on null or undefined
该call()
方法允许您指定方法的上下文,基本上使这两个调用等效:
someObject.slice(1, 2);
slice.call(someObject, 1, 2);
除了前者要求该slice
方法存在于someObject
原型链中(就像它所做的那样Array
),而后者则允许将上下文(someObject
)手动传递给该方法。
另外,后者的缩写为:
var slice = Array.prototype.slice;
slice.call(someObject, 1, 2);
与以下内容相同:
Array.prototype.slice.call(someObject, 1, 2);
Maybe a bit late, but the answer to all of this mess is that call() is used in JS for inheritance. If we compare this to Python or PHP, for example, call is used respectively as super().init() or parent::_construct().
This is an example of its usage that clarifies all:
Reference: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance