我知道它是用来使参数成为一个真正的数组,但我不明白当使用Array.prototype.slice.call(参数);时会发生什么。
当前回答
首先,您应该了解JavaScript中的函数调用是如何工作的。我想这就足以回答你的问题了。但下面是正在发生的事情的总结:
slice从Array的原型中提取slice方法。但是直接调用它不会起作用,因为它是一个方法(不是一个函数),因此需要一个上下文(一个调用对象,这个),否则它会抛出Uncaught TypeError: Array.prototype.slice调用null或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);
其他回答
当正常调用.slice()时,这是一个数组,然后它只是迭代该数组,并完成它的工作。
//ARGUMENTS
function func(){
console.log(arguments);//[1, 2, 3, 4]
//var arrArguments = arguments.slice();//Uncaught TypeError: undefined is not a function
var arrArguments = [].slice.call(arguments);//cp array with explicity THIS
arrArguments.push('new');
console.log(arrArguments)
}
func(1,2,3,4)//[1, 2, 3, 4, "new"]
也许有点晚了,但所有这些混乱的答案是,在JS中使用call()进行继承。 如果我们将其与Python或PHP进行比较,例如,调用分别用作super().init()或parent::_construct()。
这是它的用法的一个例子,阐明了所有:
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}
参考:https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
// 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]
别忘了,这种行为的底层基础是完全集成在js引擎中的类型转换。
Slice只接受object(多亏了已有的参数。Length属性),并在对其执行所有操作后返回数组对象。
如果你试图用INT-value来处理String-method,你可以测试相同的逻辑:
String.prototype.bold.call(11); // returns "<b>11</b>"
这就解释了上面的表述。
当正常调用.slice()时,底层发生的事情是,这是一个数组,然后它只是迭代该数组,并完成它的工作。
这是如何在.slice()函数数组?因为当你这样做的时候:
object.method();
...对象自动成为this在方法()中的值。所以有:
[1,2,3].slice()
...数组[1,2,3]被设置为.slice()中的this值。
但是如果你可以用别的东西代替这个值呢?只要你替换的东西有一个数值的。length属性,还有一堆数值索引的属性,它就可以工作。这种类型的对象通常称为类数组对象。
.call()和.apply()方法允许您在函数中手动设置this的值。因此,如果我们在.slice()中将this的值设置为一个类似数组的对象,.slice()将假设它正在处理一个数组,并将执行它的任务。
以这个普通对象为例。
var my_object = {
'0': 'zero',
'1': 'one',
'2': 'two',
'3': 'three',
'4': 'four',
length: 5
};
这显然不是一个数组,但如果你可以将它设置为.slice()的This值,那么它就会工作,因为它看起来足够像一个数组,让.slice()正常工作。
var sliced = Array.prototype.slice.call( my_object, 3 );
例如:http://jsfiddle.net/wSvkv/
正如你在控制台看到的,结果是我们所期望的:
['three','four'];
这就是当你将参数对象设置为.slice()的this值时所发生的情况。因为参数有一个.length属性和一堆数值索引,.slice()就像在一个真正的数组上工作一样。