JavaScript this Keyword
本文最后更新于 2024年3月6日 晚上
在 JavaScript 中,可以在全局和函数上下文中使用 this 关键字。此外,this 关键字的行为在严格模式和非严格模式之间变化。
What is this keyword
this 在不同的上下文中引用不同的对象。
假设有一个对象 counter,它有一个方法 next()。当调用 next() 方法时,就可以访问 this 对象。
1 |
|
在 next() 函数中, this 引用 counter 对象。
1 |
|
next() 是一个函数,它是 counter 对象的属性。因此,在 next() 函数内部, this 引用了 counter 对象。
Global context
在全局上下文中,this 引用全局对象,即 Web 浏览器上的 window 或 Node.js 上的 global。
此行为在严格模式和非严格模式下都是一致的。这是网络浏览器上的输出:
1 |
|
如果在全局上下文中为该对象分配属性,JavaScript 会将该属性添加到全局对象:
1 |
|
Function context
在 JavaScript 中,可以通过以下方式调用函数:
- Function invocation
- Method invocation
- Constructor invocation
- Indirect invocation
每个函数调用都定义其自己的上下文。因此, this 的行为有所不同。
Simple function invocation
在非严格模式下,函数调用时 this 引用全局对象,如下:
1 |
|
当调用 show() 函数时, this 引用全局对象,该对象在 Web 浏览器中是 window ,在 Node.js 中是 global 。
调用 show() 函数与以下内容相同:
1 |
|
在严格模式下,JavaScript 将函数内的 this 设置为 undefined
。
1 |
|
注意,严格模式自 ECMAScript 5.1 起就可用。严格模式适用于函数和嵌套函数。
1 |
|
Method invocation
当调用对象的方法时,JavaScript 将 this 设置为拥有该方法的对象。
1 |
|
在此示例中,getBrand() 方法中的 this 对象引用了 car 对象。
由于方法是对象的属性值,因此可以将其存储在变量中。
1 |
|
然后通过变量调用方法
1 |
|
你会得到 undefined 而不是“Honda”,因为当你调用一个方法而不指定其对象时,JavaScript 在非严格模式下将其设置为全局对象,在严格模式下将其设置为 undefined。
要解决此问题,可以使用 Function.prototype 对象的 bind() 方法。 bind() 方法创建一个新函数,该函数的 this 关键字设置为指定值。
1 |
|
在此示例中,当调用 brand() 方法时,this 关键字将绑定到 car
对象。
1 |
|
在此示例中,bind() 方法将 this 设置为 bike
对象,因此,可以在控制台上看到 bike
对象的品牌属性的值。
Constructor invocation
当使用 new 关键字创建函数对象的实例时,将该函数用作构造函数。
以下示例声明一个 Car 函数,然后将其作为构造函数调用:
1 |
|
表达式 new Car(‘Honda’) 是 Car 函数的构造函数调用。
JavaScript 创建一个新对象并将 this
设置为新创建的对象。这种模式在只有一个潜在问题时效果很好。
现在,可以将 Car() 作为函数或构造函数调用。如果省略 new 关键字,如下所示:
1 |
|
为了确保始终使用构造函数调用来调用 Car() 函数,请在 Car() 函数的开头添加一个检查,如下所示:
1 |
|
ES6 引入了一个名为 new.target 的元属性,它允许检测函数是作为简单调用还是作为构造函数来调用。
1 |
|
Indirect Invocation
在 JavaScript 中,函数是一等公民。换句话说,函数是对象,是 Function 类型的实例。
Function 类型有两个方法: call() 和 apply() 。这些方法允许在调用函数时设置 this 值。
1 |
|
apply() 方法与 call() 方法类似,只是它的第二个参数是参数数组。
1 |
|
Arrow function
ES6 引入了一个新概念,称为箭头函数。在箭头函数中,JavaScript 按词法设置 this。
这意味着箭头函数不会创建自己的执行上下文,而是从定义箭头函数的外部函数继承 this 。
1 |
|
在此示例中, this 值设置为全局对象,即 Web 浏览器中的 window。
由于箭头函数不会创建自己的执行上下文,因此使用箭头函数定义方法会导致问题。
1 |
|
在 getSpeed() 方法中, this 值引用全局对象,而不是 Car 对象,但全局对象没有名为 speed 的属性。因此,getSpeed() 方法中的 this.speed 返回 undefined。