很多人经常用Array.prototype.slice.call(arguments, 0)来处理函数的参数,它本质是arguments想使用数组的slice这个方法返回一个新的数组,今天就来讲讲这段代码是如何来工作的。
注意:
- Array是构造函数
- arguments是类数组对象(不是一个真正的数组,缺少很多数组的方法)
- call让一个对象调用另一个对象的方法。也可以用apply(),主要实现继承:写一个方法,然后让新的对象继承它而不是在新对象里再写一次这个方法
- slice从一个数组中切割,返回新的数组,不修改原数组
Array.prototype.slice.call(arguments, [0, arguments.length])
// 使用prototype只是因为Array是构造函数
Array.prototype.slice.call([0, 1, 2, 3, 4, 5], 0); // 输出 [0, 1, 2, 3, 4, 5]
[].slice.call([0, 1, 2, 3, 4, 5], 1); // 输出 [1, 2, 3, 4, 5]
// 如果是没有length的对象
let obj = {
length: 2,
0: 'first',
1: 'second'
};
Array.prototype.slice.call(obj); // 输出 ['first', 'second']
Array.prototype.slice.call(obj, 1); // 输出 ['second']
let obj1 = {
0: 'first',
1: 'second'
};
Array.prototype.slice.call(obj1, 1); // 因为没有length,则截取到的是空数组,输出 []
slice内部实现:
Array.prototype.slice = function(start, end) {
let result = new Array();
start = start || 0;
// this指向调用的对象,当用了call则改变this指向,this指向传进来的对象,这个关键!
end = end || this.length;
for(let i = start; i< end; i++) {
result.push(this[i]);
}
return result;
}
转成数组的通用函数:
let toArray = function(value) {
try {
return Array.prototype.slice.call(value);
} catch {
let arr = [];
for (let i = 0; i < value.length; i++) {
// arr.push(value[i]);
arr[i] = value[i]; // 这个快
}
return arr;
}
}