JavaScript-类方法中this指向问题

this关键字

与其他语言相比,函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别。它是当前执行上下文(global、function 或 eval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。

全局上下文

无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。

Note: 你可以使用 globalThis 获取全局对象,无论你的代码是否在当前上下文运行。 

      // 在浏览器中, window 对象同时也是全局对象:
      console.log(this === window); // true

      a = 37;
      console.log(window.a); // 37

      this.b = "MDN";
      console.log(window.b); // "MDN"
      console.log(b); // "MDN"

 

函数上下文

在函数内部,this的值取决于函数被调用的方式。

因为下面的代码不在严格模式下,且 this 的值不是由该调用设置的,所以 this 的值默认指向全局对象,浏览器中就是window。

//在浏览器中:
console.log(f1() === window);   // true

//在Node中:
console.log(f1() === globalThis); // true

 然而在严格模式下,如果进入执行环境时没有设置 this 的值,this 会保持为 undefined,如下:

      function f2() {
        "use strict"; // 这里是严格模式
        return this;
      }

      console.log(f2() === undefined); // true

 一个JavaScript类示例:

class Person {
        constructor(name, age) {
          this.name = name;
          this.age = age;
        }
        study() {
          console.log(this);
        }
      }

      const p = new Person("Tom", 18);
      p.study(); // Person {name: 'Tom', age: 18}
      const x = p.study;
      x(); //  undefined

灵魂三连问:

1、study方法放在了哪里?—— Person类的原型对象上(Person.prototype)

2、谁调用了study方法?——    供Person类的实例使用(这里指p)

3、study方法中this是谁?——  Person类实例

控制台输出如图:

JavaScript-类方法中this指向问题_第1张图片

 接下来做这么一个操作:

 const x = p.study;
 x(); //  undefined

将右边实例对象p的study方法传给左边常量x,然后调用x(),控制台输出undefined。小朋友,你是否有很多问号?为什么 通过赋值的方式,函数内部this的指向会发生改变?那解释这个问题之前,首先你需要明白一点,这里的常量x只是指向p中study方法,并不是调用。换句话说因为study是被直接调用的,而不是作为对象的属性或方法调用的,而能够使函数上下文this指向undefined的情况,上面提到了,就是在严格模式下,问题又来了,我们写的示例代码中没有在严格模式下编写啊,这么阴间的嘛(<_<),哪位道友鬼使神差地加上去的?

这是因为根据 JavaScript 的语法规则,所有在类中定义的方法都默认开启局部严格模式

对比下面示例中的两个函数内部this指向: 

   function func1() {
        console.log(this);
      }
      function func2() {
        "use strict";
        console.log(this);
      }
      func1(); //  window 对象信息
      func2(); //  undefined

再来完整回答上边的问题,因为常量x指向的方法 study() 是在 Person 类中定义的,其默认开启了局部严格模式。当 study() 被调用时,调用方为 window 对象,这样 this 就变成了 undefined。 

改变函数上下文this指向的方法有以下两种:ES5 引入了 bind 方法来设置函数的 this 值,而不用考虑函数如何被调用的。ES2015 引入了箭头函数,箭头函数不提供自身的 this 绑定(this 的值将保持为闭合词法上下文的值)。 

 我们只需要在Person类的构造函数内写上这么一行代码即可:

this.study = this.study.bind(this);

JavaScript-类方法中this指向问题_第2张图片  

通过调用bind方法,给Person实例上的study方法绑定了this值,因此不管是通过对象的属性或方法调用,还是直接调用,this的指向都是唯一的,即Person的实例。关于bind的其他使用这里就不深入细讲了,感兴趣的小伙伴可以自行研究。

参考:this - JavaScript | MDN  |  JavaScript 类方法中的 this 指向问题 

你可能感兴趣的:(JavaScript,javascript,前端)