call,apply,bind学习记录

31 阅读3分钟

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的学习,加油,学习前端每一天!!!