1.简介
call,apply,bind都是可以改变this指向的三种方法,主要有什么区别呢?
call: 可以传入多个参数,第一个参数是需要this指向的哪个对象;后续的参数是调用call方法函数中的参数,是一个一个传入的;
apply:可以传入多个参数,第一个参数是需要this指向的哪个对象;后续的参数是调用call方法函数中的参数,是数组形式传入的;
bind:传入的参数是和call是一样的;但是与call,apply不同的一点是,call与apply调用之后会自动执行函数方法,返回结果;但是bind是需要手动调用的,返回一个函数;
2.实操demo
定义Per与Per1两个对象如下:
let Per={
name:'coco',
say(age,sex){
console.log(`我叫${this.name}年龄是${age}性别是${sex}`)
}
}
let Per1={
name:'taotao'
}
//我们可以打印下Per.say(14,'女')
Per.say(14,'女') //我叫coco年龄是14性别是女
使用原生的call,apply,bind来看下
Per.say.call(Per1,23,'男') //我叫taotao年龄是23性别是男
Per.say.apply(Per1,[26,'男']) //我叫taotao年龄是26性别是男
let fun=Per.say.bind(Per1,,28,'男')
console.log(fun) //打印结果如下
// ƒ say(age,sex){
// console.log(`我叫${this.name}年龄是${age}性别是${sex}`)
// }
fun() //需要手动调用 //我叫taotao年龄是28性别是男
接下里我们自己动手实现下:
1.call
代码如下:
Function.prototype.myCall=function(context){
//context 指的是需要this指向的对象,就像上面的例子一样,指的是Per1
//context存在不,存在即是对象本身,不存在指向window
context=context || window
// this指的是需要改变this指向的方法对象,如上面的例子即是Person.say方法
// 我们需要的操作就是在context对象上挂载一个同样的方法指向this即可;又因为say是唯一的,我们需要Symbol来帮忙
const fn=Symbol()
context[fn]=this
console.log(context[fn])
// 打印结果是
// ƒ say(age,sex){
// console.log(`我叫${this.name}年龄是${age}性别是${sex}`)
// }
// 处理参数,call方法中第一个参数是指需要指向this的对象,后面的参数就是需要改变this的方法中的参数
let args=[...arguments].slice(1) || [] //截取参数除了第一个参数外的所有参数
let result=context[fn](...args) //调用挂载的方法
delete context[fn] //删除加上的方法
return result //返回结果
}
Per.say.myCall(Per1,13,'女') ///我叫taotao年龄是13性别是女
2.apply
代码如下:
Function.prototype.myApply=function(context){
context=context || window
let fn=Symbol()
context[fn]=this
let args=arguments[1] || [] //传入的参数是数组的形式,如果没有传入定义为空数组,为了后面好解构
console.log(args) // 打印结果是[12, '男']
let result=context[fn](...args)
delete context[fn]
return result
}
Per.say.myApply(Per1,[12,'男']) //我叫taotao年龄是12性别是男
3.bind
代码如下:
Function.prototype.myBind=function(context){
context=context||window
//定义self,保存this,在返回的函数中使用
let self=this
//先获取外部参数
let args=[...arguments].slice(1) || []
//返回一个函数,手动调用
return function(){
// 在获取内部函数的参数,因为bind传参是可以柯里化的
let newArgs=[...arguments] ||[]
// 合并后的参数
let resArgs=[...args,...newArgs]
//直接使用apply方法来改变this的指向
self.apply(context,resArgs)
}
}
let fun=Person.say.myBind(Person1,14,'男')
fun() 我叫taotao年龄是14性别是男
//还可以下面的传参,都是可以实现的
let fun=Person.say.myBind(Person1,14)
fun('男') 我叫taotao年龄是14性别是男
总结:简单的记录下call,apply,bind的学习,加油,学习前端每一天!!!