this优先级与箭头函数

242 阅读3分钟

我们之前了解了函数调用中的this绑定的四条规则,你需要做的就是找到函数的调用位置并判断应当应用哪条规则。但是如果某个调用位置可以应用多条规则怎么办呢。这就是我们要介绍的了,接着来看吧!

毫无疑问,默认绑定是四条规则中优先级最低的,所以我们可以先不考虑它。

显式>隐式

      function foo() {
        console.log(this.a);
      }

      const obj1 = {
        a: 2,
        foo: foo,
      };
      const obj2 = {
        a: 4,
      };

      obj1.foo.call(obj2)//4

new绑定>隐式

      function Foo() {
        this.a = "2";
      }
      const obj = {
        a: 3,
        Foo: Foo,
      };
      const person = new obj.Foo();
      console.log(person.a); //2
      //new > 隐式

new绑定>显式

      function foo(a) {
        this.a = a;
      }
      var obj1 = {};
      var bar = foo.bind(obj1); //将this绑定到obj1

      bar(2);
      console.log(obj1.a); //2

      var baz = new bar(3);
      console.log(obj1.a); //2 ???
      console.log(baz.a); //3

      //修改了硬绑定到obj1的this

这里和我们之前说的不一样,因为this已经硬绑定obj1了,但是new bar(3)后本来应该是变成了3的却还是2!我丢,这我们之前说的有点不一样啊,不是硬绑定就不可以改this了嘛(其实我也还没想出来,想到后会更新本篇文章!)。

综上所述,优先级:new绑定>显式绑定>隐式绑定>默认绑定

判断this的方法

  1. 函数是否在new中调用,如果是的话,this绑定的就是新创建的对象。var bar=new Bar()
  2. 函数是否通过call,apply(显式绑定)或者硬绑定?如果是的话,this绑定就是指定的对象。
  3. 函数是否在某个上下文中调用(隐式绑定)?如果是的话,this绑定的就是那个上下文对象。
  4. 如果都不是的话,使用默认绑定,如果在严格模式下,就绑定到undefiend,否则绑定到全局对象。

上述的方法只能从从上往下去判断,并且这些方法对于正常的函数调用来说已经够了,除了一些例外!请移步上一篇文章!

箭头函数=>

一个逍遥在this绑定规则外的就是ES6的箭头函数了!它并不适用this的四种规则,而是根据外层(函数或者全局)作用域来决定this。

      function foo() {
        return (a) => {
          //this继承自foo
          console.log(this.a);
        };
      }
      const obj1 = {
        a: 2,
      };
      const obj2 = {
        a: 3,
      };
      const bar = foo.call(obj1);
      bar.call(obj2); //2  不是3!

在声明bar的时候,把foo的this绑定到obj1 this也会绑定到obj1,在执行返回的箭头函数的时候 不受显式绑定限制,箭头函数的绑定无法修改,( new也不行!)

箭头函数最常用于回调函数中,例如事件处理器或者定时器:


      function foo() {
        setTimeout(() => {
          console.log(this.a);
        }, 300);
      }

      const obj = {
        a: 2,
      };
      foo.call(obj); //2

箭头函数可以像bind(…)一样确保函数的this被绑定到指定对象,此外,其重要性还体现它更常见的词法作用域取代了传统的this机制,实际上在ES6之前我们就已经使用了一种几乎和箭头函数完全一样的模式

      const obj = {
        a: 2,
      };
      function bar() {
        const that = this;
        setTimeout(function () {
          console.log(that.a);
        }, 200);
      }
      bar.call(obj); //2

虽然that=this和箭头函数看起来都可以取代bind,但是从本质上来说,它们想替代的是this的机制。