理解:Paw Patrol 解释的 JavaScript 中的上下文、范围、执行上下文和 8 种不同的 This 值!

2025-06-04

理解:Paw Patrol 解释的 JavaScript 中的上下文、范围、执行上下文和 8 种不同的 This 值!

在为职业培训和大学生讲解前端六年多之后,我发现理解 JavaScript 中保留字“this”的用法非常困难。随着 TypeScript 和 Angular 等框架的出现,这个保留字的问题已经被掩盖,尽管在这些层级之下仍然有 JavaScript,而知识的缺乏会导致需要花费数小时才能修复的错误。

上下文与范围

我们要澄清的第一个概念是上下文作用域之间的区别。许多前端开发人员都混淆了这两个术语(我自己也花了一段时间才理解它们)。

所有函数都具有关联的作用域和上下文。作用域定义了函数调用时对其变量的访问权限。另一方面,上下文始终是保留字的值,this该保留字是对拥有代码执行权的对象的引用。

执行上下文

JavaScript 是单线程语言,因此它一次只能执行一个任务。其余任务则在执行上下文中排队。可惜的是,他们说的“执行上下文”指的是作用域(为什么这么说呢?)。

在每次调用中,函数都会将其上下文附加到执行上下文中。因此,每个函数都会创建自己的执行上下文(即自己的作用域)。

一旦调用结束,上下文就会被销毁,执行上下文将转移到父上下文。全局上下文只有一个,但函数上下文有限。

“this” 指的是全局对象

默认情况下,执行的执行上下文是全局的,这意味着如果代码作为简单函数调用的一部分执行,那么“this”指的是全局对象。在浏览器中运行代码时,全局对象是“window”对象;而在 Node.js 中,全局对象可以是特殊的“global”或“module.exports”。

以下代码在浏览器中运行。

以下代码在node.js环境中运行。

“this” 指的是新实例

当使用“new”关键字调用一个函数时,该函数称为构造函数,并返回一个新实例。在这种情况下,“this”的值指向新创建的实例。

new关键字执行以下四项任务:

  1. 它创建新的空对象,例如 obj = { };
  2. 它将新的空对象的不可见“prototype”属性设置为构造函数可见且可访问的“prototype”属性。(每个函数都有可见的“prototype”属性,而每个对象都包含不可见的“prototype”属性)
  3. 它将用关键字声明的属性或函数绑定this到新对象。
  4. 除非构造函数返回非原始值(自定义 JavaScript 对象),否则它会返回一个创建的对象。如果构造函数不包含 return 语句,编译器会在函数末尾隐式插入“return this;”。如果构造函数返回原始值,则return this;不会插入 return this;。

现在我们有了新的执行上下文,可以为 Dog 函数定义新的属性,在本例中,我们有了 2 只新狗:Paw Patrol、Turbot 和 Rubble。

您可能知道,Javascript 的巨大优势在于使用每个函数的原型(我建议您阅读其他面向对象语言中使用的原型模式,因为它们不是原生的)。

“this” 指的是调用者对象(父对象)

在 JavaScript 中,对象的属性可以是函数,也可以是简单的值。当调用对象的方法时,“this”指向包含被调用方法的对象。

在下面的例子中,您可以看到 this 值如何根据执行上下文而不同。

“this” 与 call 或 apply 方法

JavaScript 中的函数也是一种特殊的对象。每个函数都拥有callbindapply方法。这些方法可用于将 this 的自定义值设置为函数的执行上下文。

在下面的代码中,您可以看到如何使用调用方法改变执行上下文。

带有 bind 方法的“this”

bind方法返回一个新方法,其中“this”指的是传递的第一个参数。

带有粗箭头函数的“this”

作为 ES6 的一部分,引入了一种定义函数的新方法;使用fat arrow(=>)。

当使用粗箭头时,它不会为“this”创建新的值。“this”在函数外部继续引用它所引用的同一个对象。没有新的执行上下文。

下面的代码中this的值是其执行上下文中growUp没有属性的函数。age

在这种情况下,解决方案不是创建新的执行上下文。因此,我们可以使用胖箭头。

带有粗箭头函数和apply-call的“this”

当你对箭头函数使用 apply 或 call 方法时,this不会改变,因为箭头函数本身并不拥有this。因此,apply 和 call 方法只会调用带有参数的原始方法,而 thisArg 会被忽略。

带有类糖语法的“this”

当我们使用class语法糖时,通常使用this与其他面向对象编程语言相同的方式。然而,大多数面向对象编程语言不允许在函数中定义函数。

因此,如果我们查看以下代码,会发现一个方法
displayName包含一个innerDisplay使用
关键字的方法this。如果我们innerDisplay在此上下文中执行函数,我们将创建一个新的执行上下文,因此this值将不属于Dog类。不过,为了解决这个问题,我们可以使用本博客中介绍的任何技巧。在本例中,我们将使用function 将函数apply的上下文更改为 的上下文。innerDisplayDog

更多,更多,更多……


*最初于 2019 年 5 月 17 日发布于https://www.carloscaballero.io 。

文章来源:https://dev.to/carlillo/understanding-context-scope-execution-context-and-8- Different-this-value-in-javascript-explained-by-paw-patrol-2gme
PREV
理解设计模式:建造者
NEXT
重构:保护条款