[].slice.call(arguments)作用:把arguments转换为数组。
等同于[...arguments]。
那么内部实现原理呢?
这里就需要先清楚数组的slice()和函数的call(obj,arg1,arg2,...)的实现原理。
首先了解下call()方法:
Function.call(obj,arg1,arg2,...)的作用:把Function内部的this指向obj这个对象。
举例看看:
function test(){
console.log(this) // {a: 1, b: 2}
}
const obj = {
a:1,
b:2
}
test.call(obj)
//从输出结果来看,确实是指向了obj对象
//那我给test()加个属性看看
function test(name){
this.name = name
console.log(this) // {a: 1, b: 2, name: "yy"}
}
const obj = {
a:1,
b:2
}
test.call(obj,'yy')
//从结果可看到,此时this指向的并不是obj这个对象,而是由函数内部的属性、方法(如果有的话)与obj对象内部的属性、方法组成的新对象。
//所以call()的作用得修正过来,并不是指向的是那个传入的obj对象,而是一个新的obj对象。
再来看下:数组的slice()。
//这是一个简洁版的slice()内部实现过程。
Array.prototype.slice=function(start,end){
let result = new Array(); //创建一个新数组
let start = start || 0;
let end = end || this.length; //this指向的是调用slice()的数组
for(let i=start; i<end; i++){
result.push(this[i]);
}
return result; //返回一个新的数组
}
slice()内部会去遍历数组内的每一个元素(前提是没有传入start参数、end参数),把遍历到的元素存放到一个空数组,遍历结束,再把这个空数组返回。作用有点像拷贝。
当把slice()与call()结合后,由于call()的作用,slice()内部的this指向了新的对象。
看下面的例子。
Array.prototype.slice=function(start,end){
let result = new Array(); //创建一个新数组
let start = start || 0;
let end = end || this.length; //this指向发生改变
for(let i=start; i<end; i++){
result.push(this[i]);
}
return result; //返回一个新的数组
}
function fn(){
let res = [].slice.call(arguments) /
console.log(res)//[1,2,3]
}
fn(1,2,3)
arguments:是个类数组,但是也有length属性,所以在slice()内部可以对arguments进行遍历,把arguments内部的元素遍历后,组成数组返回。所以最后呈现给我们的结果就是把arguments转变为了数组。
最后我想说明一点:在上面的例子中slice()内部的this在call()的作用指向了arguments,看似是这样,但是我给slice()内部额外加个属性试试:
Array.prototype.slice=function(name,start,end){
this.name = name //额外添加的属性
let result = new Array(); //创建一个新数组
let start = start || 0;
let end = end || this.length; //this指向发生改变,但并不指向原来的arguments,
//严格来讲,是经过组合得到的新arguments
console.log(this)//[1, 2, 3, name: "yy",...]
for(let i=start; i<end; i++){
result.push(this[i]);
}
return result; //返回一个新的数组
}
function fn(){
let res = [].slice.call(arguments,'yy')
console.log(res)//[1,2,3]
}
fn(1,2,3)
最近又看到Array.prototype.slice.call( arguments, 0 ),arguments后面又加了个数字。但是,理解不了这个数字是怎么起作用的。
var my_object = {
'0': 'zero',
'1': 'one',
'2': 'two',
'3': 'three',
'4': 'four',
length: 5
};
var sliced0 = Array.prototype.slice.call( my_object, 0 );
var sliced1 = Array.prototype.slice.call( my_object, 1);
var sliced2 = Array.prototype.slice.call( my_object, 2);
console.log(sliced0)//["zero", "one", "two", "three", "four"]
console.log(sliced1)//["one", "two", "three", "four"]
console.log(sliced2)//["two", "three", "four"]