ily*_*lyo 457 javascript prototype-programming
我知道它用于使参数成为一个真正的数组,但我不明白使用时会发生什么 Array.prototype.slice.call(arguments)
use*_*716 848
在幕后发生的事情是,当.slice()正常调用时,this是一个数组,然后它只是遍历该数组,并完成它的工作.
如何this在.slice()函数中使用数组?因为当你这样做时:
object.method();
Run Code Online (Sandbox Code Playgroud)
...该object自动成为价值this的method().所以:
[1,2,3].slice()
Run Code Online (Sandbox Code Playgroud)
...将[1,2,3]数组设置为thisin 的值.slice().
但是,如果你可以用其他东西替代this价值呢?只要你替换的任何东西都有一个数字.length属性,并且有一堆属性是数字索引,它应该可以工作.这种类型的对象通常称为类似数组的对象.
使用.call()和.apply()方法可以手动设置this函数的值.因此,如果我们设定的值,this在.slice()一个类似数组的对象,.slice()将只承担它的工作与Array,并会做它的东西.
以此普通对象为例.
var my_object = {
'0': 'zero',
'1': 'one',
'2': 'two',
'3': 'three',
'4': 'four',
length: 5
};
Run Code Online (Sandbox Code Playgroud)
这显然不是一个数组,但是如果你可以将它设置为this值.slice(),那么它就可以正常工作,因为它看起来就像一个数组,.slice()可以正常工作.
var sliced = Array.prototype.slice.call( my_object, 3 );
Run Code Online (Sandbox Code Playgroud)
示例: http ://jsfiddle.net/wSvkv/
正如您在控制台中看到的,结果是我们所期望的:
['three','four'];
Run Code Online (Sandbox Code Playgroud)
所以当你将一个arguments对象设置为this值时会发生这种情况.slice().因为它arguments有一个.length属性和一堆数字索引,所以.slice()就像它在一个真正的数组上工作一样.
Ben*_*ing 81
该arguments对象实际上不是Array的实例,并且没有任何Array方法.因此,arguments.slice(...)不起作用,因为arguments对象没有slice方法.
数组确实有这种方法,因为arguments对象与数组非常相似,所以两者是兼容的.这意味着我们可以使用带有arguments对象的数组方法.由于数组方法是在构建数组时考虑的,因此它们将返回数组而不是其他参数对象.
为什么要使用Array.prototype?这Array是我们从(new Array())创建新数组的对象,这些新数组是传递方法和属性,如slice.这些方法存储在[Class].prototype对象中.因此,为了提高效率,我们不是通过(new Array()).slice.call()或访问切片方法[].slice.call(),而是直接从原型中获取.这样我们就不必初始化一个新数组了.
但为什么我们必须首先做到这一点?好吧,正如你所说,它将一个arguments对象转换为一个Array实例.然而,我们使用切片的原因更多的是"黑客"而不是任何东西.切片方法将采用,您猜对了,切片的数组并将该切片作为新数组返回.不传递任何参数(除了参数对象作为其上下文)会导致slice方法获取传递的"数组"的完整块(在本例中为arguments对象)并将其作为新数组返回.
Del*_*ani 42
通常,打电话
var b = a.slice();
Run Code Online (Sandbox Code Playgroud)
将数组复制a到b.但是,我们做不到
var a = arguments.slice();
Run Code Online (Sandbox Code Playgroud)
因为arguments它不是一个真正的数组,并没有slice作为一种方法.Array.prototype.slice是slice数组的函数,并call使用thisset to 运行函数arguments.
sam*_*sam 21
// We can apply `slice` from `Array.prototype`:
Array.prototype.slice.call([]); //-> []
// Since `slice` is available on an array's prototype chain,
'slice' in []; //-> true
[].slice === Array.prototype.slice; //-> true
// … we can just invoke it directly:
[].slice(); //-> []
// `arguments` has no `slice` method
'slice' in arguments; //-> false
// … but we can apply it the same way:
Array.prototype.slice.call(arguments); //-> […]
// In fact, though `slice` belongs to `Array.prototype`,
// it can operate on any array-like object:
Array.prototype.slice.call({0: 1, length: 1}); //-> [1]
Run Code Online (Sandbox Code Playgroud)
Mar*_*Roy 18
首先,您应该阅读函数调用在JavaScript中的工作原理.我怀疑只有这一点足以回答你的问题.但这里是对正在发生的事情的总结:
Array.prototype.slice提取方法从的原型.但直接调用它是行不通的,因为它是一个方法(不是一个函数),因此需要一个上下文(一个调用对象),否则就会抛出.slice ArraythisUncaught TypeError: Array.prototype.slice called on null or undefined
该call()方法允许您指定方法的上下文,基本上使这两个调用等效:
someObject.slice(1, 2);
slice.call(someObject, 1, 2);
Run Code Online (Sandbox Code Playgroud)
除了前者要求slice方法存在于someObject原型链中(就像它所做的那样Array),而后者允许将context(someObject)手动传递给方法.
此外,后者简称:
var slice = Array.prototype.slice;
slice.call(someObject, 1, 2);
Run Code Online (Sandbox Code Playgroud)
这与以下相同:
Array.prototype.slice.call(someObject, 1, 2);
Run Code Online (Sandbox Code Playgroud)
小智 12
Array.prototype.slice.call(arguments)是将参数转换为数组的传统方式.
在ECMAScript 2015中,您可以使用Array.from或spread运算符:
let args = Array.from(arguments);
let args = [...arguments];
Run Code Online (Sandbox Code Playgroud)
这是因为,正如MDN所说
arguments对象不是数组.它类似于数组,但除了length之外没有任何数组属性.例如,它没有pop方法.但是它可以转换为真实数组:
在这里,我们调用slice本机对象Array而不是它的实现,这就是额外的原因.prototype
var args = Array.prototype.slice.call(arguments);
Run Code Online (Sandbox Code Playgroud)