我知道它是用来使参数成为一个真正的数组,但我不明白当使用Array.prototype.slice.call(参数);时会发生什么。
它使用slice方法数组have并调用它,它的this是arguments对象。这意味着它会像调用arguments.slice()一样调用它,假设参数有这样一个方法。
创建一个不带任何参数的切片将简单地获取所有元素——因此它只是简单地将元素从参数复制到数组中。
通常,调用
var b = a.slice();
将数组a复制到b中。然而,我们不能
var a = arguments.slice();
因为参数没有slice作为方法(它不是一个真正的数组)。
Array.prototype.slice是数组的slice函数。.call运行这个slice函数,并将this值设置为参数。
假设你有:function。apply(thisArg, argArray)
apply方法调用一个函数,传入将绑定到this的对象 和一个可选的参数数组。
slice()方法选择数组的一部分,并返回新数组。
当你调用array。prototype。slice。Apply (arguments,[0])在参数上调用数组切片方法(bind)。
正如MDN所指出的,这是因为
arguments对象不是数组。它类似于数组,但是 除了长度以外,没有任何数组属性。例如,它确实如此 没有pop方法。然而,它可以转换为一个真正的数组:
这里我们是在原生对象Array上调用slice,而不是在它的实现上调用slice,这就是为什么要使用额外的.prototype
var args = Array.prototype.slice.call(arguments);
arguments对象实际上不是Array的实例,也没有任何Array方法。因此,arguments.slice(…)将不起作用,因为arguments对象没有slice方法。
数组确实有这个方法,因为arguments对象与数组非常相似,所以两者是兼容的。这意味着我们可以在arguments对象中使用数组方法。由于数组方法是在考虑数组的情况下构建的,因此它们将返回数组而不是其他参数对象。
为什么使用array。prototype呢?Array是我们用来创建新数组的对象(new Array()),这些新数组被传递方法和属性,比如slice。这些方法存储在[Class]中。原型对象。因此,为了提高效率,我们不通过(new Array()).slice.call()或[].slice.call()来访问slice方法,而是直接从原型中获取它。这样我们就不必初始化一个新数组。
But why do we have to do this in the first place? Well, as you said, it converts an arguments object into an Array instance. The reason why we use slice, however, is more of a "hack" than anything. The slice method will take a, you guessed it, slice of an array and return that slice as a new array. Passing no arguments to it (besides the arguments object as its context) causes the slice method to take a complete chunk of the passed "array" (in this case, the arguments object) and return it as a new array.
当正常调用.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()就像在一个真正的数组上工作一样。
别忘了,这种行为的底层基础是完全集成在js引擎中的类型转换。
Slice只接受object(多亏了已有的参数。Length属性),并在对其执行所有操作后返回数组对象。
如果你试图用INT-value来处理String-method,你可以测试相同的逻辑:
String.prototype.bold.call(11); // returns "<b>11</b>"
这就解释了上面的表述。
// 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]
当正常调用.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"]
首先,您应该了解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);
也许有点晚了,但所有这些混乱的答案是,在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
array. prototype.slice.call(参数)是将参数转换为数组的老式方法。
在ECMAScript 2015中,你可以使用Array.from或展开操作符:
let args = Array.from(arguments);
let args = [...arguments];
Array.prototype.slice=function(start,end){
let res=[];
start=start||0;
end=end||this.length
for(let i=start;i<end;i++){
res.push(this[i])
}
return res;
}
当你这样做时:
Array.prototype.slice.call(arguments)
Arguments在slice中变成this的值,然后slice返回一个数组
/*
arguments: get all args data include Length .
slice : clone Array
call: Convert Object which include Length to Array
Array.prototype.slice.call(arguments):
1. Convert arguments to Array
2. Clone Array arguments
*/
//normal
function abc1(a,b,c){
console.log(a);
}
//argument
function: function abc2(){
console.log(Array.prototype.slice.call(arguments,0,1))
}
abc1('a','b','c');
//a
abc2('a','b','c');
//a