JavaScript 类方法中的 this 指向问题

一个简单的 JavaScript 类示例javascript

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

const p = new Person('Callback', 27)
p.speak();
复制代码

执行上面的示例能够看到控制台输出以下图java

接下来作一个操做:markdown

const f = p.speak
f() // 输出 undefined
复制代码

这里将常量 f 指向 speak() 方法,注意这里是「指向」,并非「调用」。以后调用 f() 能够观察到控制台输出为 undefined。那么问题来了,为何这么赋值以后,函数内部的 this 再也不是 Person 的实例 p 而变成了 undefined函数

实际上,方法内部的 this 永远指向的是调用这个方法的对象,经过 Person 的实例 p 调用 speak() 方法,那么 this 就指向 p。后面将 speak 赋值给常量 f 后, f() 表示的就是经过全局的 window 对象来调用 f() 方法。按理说,f() 方法被调用时应该输出 window 对象的信息,但这里输出的倒是 undefined。这是由于根据 JavaScript 的语法规则,全部在类中定义的方法都默认开启局部严格模式。在严格模式下,全部指向 window 对象的 this,都所有变动为 undefined。看下面的示例:ui

function demo() {
  console.log(this)
}
function demo2() {
 'use strict'
  console.log(this)
}
demo() // 输出 window 对象信息
demo2() // 输出 undefined
复制代码

回到最初的问题,之因此调用 f() 方法后输出 undefined,是由于 f 指向的方法 speak() 是在 Person 类中定义的,其默认开启了局部严格模式。当 f() 被调用时,调用方为 window 对象,这样 this 就变成了 undefinedthis

其实这一点和 Java 中对方法的处理是相似的。每个实例对象都持有对方法的引用而不是保存一份方法,方法会自动在参数列表的最前面添加一个 this 参数,这就是咱们之因此可以在 Java 方法里使用 this 关键字的缘由,而这个 this 指向的就是当前在调用这个方法的对象。区别在于,Java 里全部的方法都不能脱离定义它的类,不能够像 JavaScript 里面把类的某个方法赋值给一个全局变量或常量。spa

相关文章
相关标签/搜索