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