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]
数组设置为this
in 的值.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
使用this
set 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
Array
this
Uncaught 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)
归档时间: |
|
查看次数: |
130212 次 |
最近记录: |