call、apply和bind区别解释

156 阅读2分钟

是什么?

核心思想: 借用方法

解释: apply,call,bind都是js给函数内置的一些api,调用他们可以为函数指定this的执行,同时也可以传参。

作用: 改变函数执行时的this指向

语法

注意:fun必须是函数

fun.call(thisArg, param1, param2, ...)
fun.apply(thisArg, [param1,param2,...])
fun.bind(thisArg, param1, param2, ...)
​
Object.prototype.toString.call(data)

区别

call和apply

传递参数不同:

  • apply是第2个参数,这个参数是一个数组:传给fun参数都写在数组中。

  • call从第2~n的参数都是传给fun的,2-n都是参数。

    巧记:apply是以a开头,它传给fun的参数是Array,也是以a开头的。

call/apply与bind区别

执行方式:

  • call/apply改变了函数的this上下文后马上执行该函数
  • bind则是返回改变了上下文后的函数,不执行该函数

返回值:

  • call/apply 返回fun的执行结果
  • bind返回一个属于指定对象的fun方法

手写call、apply和bind

call、apply

  • that是指定的this对象
  • args 是参数对象
  • 利用Symbol将this对象(原函数所在对象)绑定到传入的that对象上
  • 执行结束删除临时属性
call
    // call 
    // 第一个参数是指定的this,后面的参数是参数列表
    function myCall (that = window, ...args) {
      if (!this instanceof Function) throw new TypeError("Type Error")
      if (that === null || that === undefined) that = window
​
      const fn = Symbol('fn')
      that[fn] = this
​
      const res = that[fn](...args)
      delete that[fn]
      return res
    }
​
    const obj = {
      age: 10,
      getAge: function() {
        console.log(this.age);
      }
    }
    const stu = {
      age: 18
    }
​
    Function.prototype.call = myCall
​
    obj.getAge.call(stu) // 18
apply
      // apply
      // 第一个参数绑定的是 this, 第二个参数是个数组
​
      function myApply(that = window, args = []) {
        if (!this instanceof Function) throw new TypeError("Type Error");
        if (that === null || that === undefined) that = window;
        // 使用Symbol确保不会与原对象属性产生冲突 
        const fn = Symbol("fn");
        that[fn] = this;
​
        const res = that[fn](...args);
        delete that[fn];
        return res;
      }
​
      const obj = {
        age: 10,
        getAge: function () {
          console.log(this.age);
        },
      };
      const stu = {
        age: 18,
      };
​
      Function.prototype.apply = myApply;
​
      obj.getAge.apply(stu); // 18

bind

      //bind 返回一个函数
      function myBind(that = window, ...args) {
        if (!this instanceof Function) throw new TypeError("Type Error");
        if (that === null || that === undefined) that = window
​
        const self = this;
​
        return function F() {
          // new
          if (this instanceof F) {
            return new self(...args, ...arguments);
          }
          return self.apply(that, [...args, ...arguments]);
        };
      }
      age = 20
​
      const obj = {
        age: 10,
        getAge: function () {
          console.log(this.age);
        },
      };
      const stu = {
        age: 18,
      };
​
      Function.prototype.bind = myBind;
​
      const stuAge = obj.getAge.bind(stu);
      stuAge();
      const getAge = obj.getAge.bind(null);
      getAge()

相信通过手写call、apply和bind,能够很快速的认识到它们之间的区别