apply,call,bind三者作用和区别以及手写js实现三者的功能

150 阅读2分钟

apply,call,bind是javascript提供的,三者的作用都是为了改变本身函数的this的指向,如果没有指定对象的话this自动指向全局对象,浏览器是windows,在node环境是global。

一、三个方法的的简单使用

  1. call()
function foo(a,b){
    console.log(a+b) //3
    console.log(this.name)//jennry
}
let obj = {
    name:'jennry', 
    age:'23'
}
foo.call(obj,1,2)`
2.apply()
`function foo(a,b){
    console.log(a+b)  //3
    console.log(this.name)//jennry
}
let obj = {
    name:'jennry',
    age:'23'
}
foo.apply(obj,[1,2])`
3.bind()
`function foo(a,b){
    console.log(a+b) //3
    console.log(this.name)/jennry
}
let obj = {
    name:'jennry',
    age:'23'
}
foo.bind(obj,1,3)()

二、三个方法的区别

call()传的参数是以逗号分隔的,apply()传的参数是以数组的形式传的,bind()方法是返回一个函数需要再次调用才会执行。

三、使用JS模拟实现call,apply,bind三个方法

1、call():

      function call(fn, obj, ...args) {
          //如果obj没有或者为空,则obj指向全局对象
          if (!obj) {
            obj = globalThis;
          }
          //将方法绑定到指定的obj对象上
          obj.temp = fn;
          //执行绑定的对象的方法并返回结果
          obj.temp(...args);
          //console.log(result)
          //删除绑定到对象的属性方法
          delete obj.temp;
          //return result
        }
        //全局对象下绑定一个属性,测试obj为null时打印的name值
        window.name = "tony";
        let obj = { name: "jenny", age: 22 };
        function foo(a, b) {
          console.log(this.name,this); //jenny  { name: "jenny", age: 22 }
          console.log(a + b);  //3
        }
        call(foo, obj, 1, 2);

2、apply()

     function apply(fn, obj, args) {
        //如果obj没有或者为空,则obj指向全局对象
        if (!obj) {
          obj = globalThis;
        }
        //将方法绑定到指定的obj对象上
        obj.temp = fn;
        //执行绑定的对象的方法并返回结果
       const result =  obj.temp(...args);
        //删除绑定到对象的属性方法
        delete obj.temp;
        return result
      }

      window.name = "tony";
      let obj = { name: "jenny", age: 22 };
      function foo(a, b) {
        console.log(this.name, this);  //jenny  { name: "jenny", age: 22 }
        console.log(a+b);//3
      }
      apply(foo, obj,[1, 2]);

3、bind()

       function call(fn, obj, ...args) {
          //如果obj没有或者为空,则obj指向全局对象
          if (!obj) {
            obj = globalThis;
          }
          //将方法绑定到指定的obj对象上
          obj.temp = fn;
          //执行绑定的对象的方法并返回结果
          obj.temp(...args);
          //console.log(result)
          //删除绑定到对象的属性方法
          delete obj.temp;
          //return result
        }
      
        window.name = "tony";
      let obj = { name: "jenny", age: 22 };
      function foo(a, b) {
        console.log(this.name, this);  //jenny  { name: "jenny", age: 22 }
        console.log(a+b);//3
      }
      function bind(fn,obj,...args){
         return function(){
            call(fn,obj,...args)
         }
      }
      bind(foo,obj,1,2)()