已被阅读 1245 次 | 文章分类:日常随笔 | 2022-03-29 00:11
call、capply、bind是函数的方法; 使用场景:如果一个对象想借用别的对象的某个方法,可以使用这三个方法。即如果自己没有方法,但别人有我们就可以去借用,不用自己实现了;
1 简介
call、capply、bind他们三个是函数的方法; 使用场景:如果一个对象想借用别的对象的某个方法,可以使用这三个方法。即如果自己没有方法,但别人有我们就可以去借用,不用自己实现了;
(1) 功能
call和apply效果一样,使用该方法的时候,会立刻执行借用的函数;
bind先获取到该借用的方法,暂不执行;
(2) 用法
call和bind一样,第一个参数是替换内部this的对象,后面是要调用函数的参数;
apply第一个参数是替换内部this的对象,后面是一个参数数组;
2 基础用法-如何调用
首先我们定义两个对象,一个小白,一个小杨
// 小白对象
let xiaobai={
name:"小白",
pet:"splider"
}
// 小杨对象
let xiaoyang={
name:'小杨',
pet:'pig',
say:function(){
console.log(`${this.name}有一只${this.pet}宠物`)
}
}
如果想输出一个结果:小白有一只宠物蜘蛛 恰好咱了解到小杨对象有一个方法可以输出这句话;所以小白对象就想能不能借用他这个方法,答案是肯定可以啊,用call、apply、bind都可以
(1)用call
// 这是小杨自己的方法
xiaoyang.say(); // 小杨有一只pig宠物
// 小白借用了小杨的say函数,输出自己想要的结果
xiaoyang.say.call(xiaobai) // 小白有一只splider宠物
所以小白借用小杨的say函数实现了自己的目的;
(2)用apply
xiaoyang.say.apply(xiaobai) // 小白有一只splider宠物
(3)用bind
xiaoyang.say.bind(xiaobai); // 不会输出任何结果
bind需要手动调用执行
xiaoyang.say.bind(xiaobai)() // 小白有一只splider宠物
// 也可以将函数存到变量,等用到的时候执行
let xiaobaiSay=xiaoyang.say.bind(xiaobai);
xiaobaiSay(); // 小白有一只splider宠物
// 也可以直接给小白对象定义一个say属性,把借用来的函数用say存下来
xiaobai.say=xiaoyang.say.bind(xiaobai);
xiaobai.say();
如果直接赋值给小白对象,那么小白对象将永远有这个方法啦;所以bind可以用来对象或者函数间的继承
3 如何传参数
如果借用的函数,需要传参数进去;除了第一个参数是对象,后面需要传入参数;
仍然以上面小杨对象为例;
// 对象xiaoyang
let xiaoyang={
name:'小杨',
pet:'pig',
say:function(petName,petAge){
console.log(`${this.name}有一只${this.pet}宠物,名字叫${petName},今年${petAge}岁`)
}
}
call、apply、bind的传参方式如下;
xiaoyang.say.call(xiaobai,'火玫瑰',2)
xiaoyang.say.apply(xiaobai,['火玫瑰',2])
xiaoyang.say.bind(xiaobai,'火玫瑰',2)()
输出结果都是一样的;apply的第二个参数传数组,但是say函数中,会自动给他展开,所以petName会对自动匹配数组第一个元素,petAge匹配第二个参数。
say函数中获取参数也可以利用arguments;如下效果是一样的
// 对象xiaoyang
let xiaoyang={
name:'小杨',
pet:'pig',
say:function(){
let [...arg]=arguments // 将类数组arguments转为正常数组Array
console.log(`${this.name}有一只${this.pet}宠物,名字叫${arg[0]},今年${arg[1]}岁`)
}
}
4 手动实现上面三个方法
首先分析下原理,其实我们上面的目的就是想让我们的对象拥有一个他没有的函数;那么这么一想就理解了;可以将要借用的函数赋值给该对象,然后在内部执行即可。如下:
先以实现call函数为例
// 在函数原型上定义一个callSelf函数
Function.prototype.callSelf = function (obj) {
obj.fn = this;
obj.fn();
delete obj.fn;
}
// 以上面例子为例
// obj就是传入的小白对象;this就是say函数;然后直接执行say函数即可
// xiaoyang.say.callSelf(xiaobai,'火玫瑰',2)
注意,需要将fn函数给删除,不然小白对象就直接一直有fn这个函数了;占内存没必要。
如果传参数的话,实现如下;利用...解析类数组参数即可;
// 手动实现函数的call方法
Function.prototype.callSelf=function(){
const [ctx, ...args] = arguments; // ctx匹配第一个参数;args将剩余参数用数组组织起来
ctx.fn=this;
ctx.fn(...args);
delete ctx.fn;
}
xiaoyang.say.callSelf(xiaobai,'火玫瑰',2)
apply和bind的实现如下:
// 手动实现函数的apply方法
Function.prototype.applySelf=function(){
const [ctx, args] = arguments;
ctx.fn=this;
ctx.fn(...args);
delete ctx.fn;
}
// 手动实现函数的bind方法,借助apply
Function.prototype.bindSelf = function () {
const [ctx, ...args] = arguments;
const self = this;
return function () {
self.apply(ctx, args);
}
}
实现bind函数时,在内部不执行fn,而是将函数返回即可;同时不删除赋值给对象的函数fn;因为他需要后续调用执行;
QQ:3410192267 | 技术支持 微信:popstarqqsmall
Copyright ©2017 xiaobaigis.com . 版权所有 鲁ICP备17027716号