JavaScript中的Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性).
首先,我们来看看JavaScript中的slice用法, 在JavaScript中Array是一个类,slice是此类中的一个方法,slice的中文意思是 ‘截取’。
slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
Array.prototype.slice.call(arguments)能够将具有length属性的arguments转换为数组, 我们可以理解为就是 arguments.toArray().slice()。
所以,这个过程是不是可以理解为Array.prototype.slice.call(arguments)的实现过程就是把传入进来的具有length属性的第一个参数arguments转换为数组,再调用它的slice(截取)方法。
这个Array.prototype.slice.call(arguments) 不单有slice方法,还有call方法。 那么call方法又是如何用的呢?
我们来看一个用call方法的例子:
var obj = {
message: 'My name is: '
}
function getName(firstName) {
console.log(this.message + firstName)
}
getName.call(obj, 'Uyi')//My name is: Uyi
从上面的代码片段中,我们可以看到调用了函数getName的call方法之后,我们可以看到把call方法中的参数传入到函数getName的作用域中去了,也就是说函数getName中的this此时指向的就是它调用的call方法中的参数。
我们上面说了,Array.Prototype.slice.call()除了call方法外,还有slice方法,那么JavaScript中Array的slice方法的内部实现是怎样的呢?
Array.prototype.slice = function(start,end){
var result = new Array();
start = start || 0;
end = end || this.length; // this指向调用的对象,当用了call后,能够改变this的指向,也就是指向传进来的对象
for(var i = start; i < end; i++)
{
result.push(this[i]);
}
return result;
}
所以整个过程我们基本就可以分2步进行理解了:
Array.prototype.slice.call(arguments)
第一步: 其中,arguments是一个具有length属性的对象, 通过call 这个方法,把arguments 指向了Array.prototype.slice方法的作用域,也就是说通过call方法,让Array.prototype.slice对arguments对象进行操作。
第二步: Array.prototype.slice就是对该对象使用Array类的slice方法。但是呢arguments它又不是个Array对象。
因为:typeof arguments === “Object” //不是"Array"
所以我们没法用arguments.slice()方法,这样是会报错的。 所以这里,我们需要使用Array.prototype.slice, 它的作用就是第一步把arguments转换为一个Array对象,第二步对转换后的Array对象使用slice方法。
理解了整个过程后,我们来看一些具体的例子:
let a = {length: 2, 0: 'hello', 1: 'world'};
console.log(Array.prototype.slice.call(a));//['hello', 'world']
let b = {0: 'hello', 1: 'world'};
console.log(Array.prototype.slice.call(b));//[]
function test(){
console.log(Array.prototype.slice.call(arguments));
console.log(Array.prototype.slice.call(arguments, 1));
}
test('11', '22', '33');
//['11', '22', '33']
//['22', '33']
实际开发中比较常用到的将函数的实际参数转换成数组的方法 :
var args = Array.prototype.slice.call(arguments),arguments 是函数内部的特殊的对象,主要用途是保存函数参数,除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用var args = [].slice.call(arguments)来代替。