本文已参与「新人创作礼」活动,一起开启掘金创作之路。
这本质是slice()函数和call()函数的一个组合应用
①、slice()是数组对象的固有方法,用来截取数组
例子:有数组arr=[2,3,4,5];
arr.slice(0); //输出:2,3,4,5
arr.slice(1,3); //输出3,4 即从下标1开始,到下标3的前一个结束
\
②、call()方法,能够改变函数的this指向
这个方法就很有意思,它给我的感觉就是能把一个对象的方法借给别人,同时将自己方法中的原本指向自己的this,改成指向别人
\
例子:
let objNokia = {
name: 'Nokia',
price: 399,
character: '砸核桃',
show: function () {
console.log(this.name + '手机,只要' + this.price + ',能' + this.character)
}
}
let objXiaoMi = {
name: 'XiaoMi',
price: 2999,
character: '当暖手宝'
}
objNokia.show.call(objXiaoMi);
objNokia.show.call(objXiaoMi) //输出:XiaoMi手机,只要2999,能当暖手宝
\
例子中小米和诺基亚有类型的数据结构,不同的是小米没有展示show这个方法,但是没关系,使用show.call(obj)可以将show方法借给obj使用,call会立即执行show函数,并且函数中的this指向改为obj
米:你的方法很棒,不如call(copy)给我吧
\
③ 、call的参数。第一个参数是借予的目标对象,后面的参数则传递给被借出去的源方法
Array.prototype.slice.call(obj, 0);能将伪数组obj转换成真正的数组
Array.prototype.slice.call(obj, 1,4); 先将伪数组转换成数组后,截取下标1~3的元素作为数组返回
事实上就是obj之后的参数被传递给了slice函数
\
为什么是Array.prototype.slice.call(obj, 0);
obj是个伪数组, 虽然自身没有数组的slice的方法,但得益于和数组有类似的数据结构,通过call借来数组的slice方法它可以完美适用(直接牛过来hhh)
但比起slice方法原本的功能(剪切数组),它的副作用才是我们的目标。运行一次slice后,它将伪数组转换成了真正的数组返回了过来,这可比for循环舒服多了
\
*再多想一步,如果考虑兼容性
可以这样写
function turnToArray(obj) {
try {
return Array.prototype.slice.call(obj);
} catch (e) {
let arr = [];
for (let index = 0; index < obj.length; index++) {
const element = obj[index];
arr.push(element)
}
return arr;
}
}
与apply函数的关系
call与apply都可以借用函数,使用方法是一样的,函数的第一个参数都是方法借予的对象,区别在于后面的参数。
call第一个参数后可以写任意个,且都会传给借用的方法。
而apply的第二个参数是一个数组,里面是要传给方法所有的参数
例子:
let obj={
0:'a',
1:'b',
2:'c',
3:'d',
length:4
};
Array.prototype.slice.call(obj, 0,3) //复制到Chrome控制台中,输出['a','b','c']
Array.prototype.slice.apply(obj, [0,2]) //复制到Chrome控制台中,输出['a','b']
欢迎任何留言!交流使人进步!