理解: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关键字执行以下四项任务:
- 它创建新的空对象,例如 obj = { };
- 它将新的空对象的不可见“prototype”属性设置为构造函数可见且可访问的“prototype”属性。(每个函数都有可见的“prototype”属性,而每个对象都包含不可见的“prototype”属性)
- 它将用关键字声明的属性或函数绑定
this
到新对象。 - 除非构造函数返回非原始值(自定义 JavaScript 对象),否则它会返回一个创建的对象。如果构造函数不包含 return 语句,编译器会在函数末尾隐式插入“return this;”。如果构造函数返回原始值,则
return this;
不会插入 return this;。
现在我们有了新的执行上下文,可以为 Dog 函数定义新的属性,在本例中,我们有了 2 只新狗:Paw Patrol、Turbot 和 Rubble。
您可能知道,Javascript 的巨大优势在于使用每个函数的原型(我建议您阅读其他面向对象语言中使用的原型模式,因为它们不是原生的)。
“this” 指的是调用者对象(父对象)
在 JavaScript 中,对象的属性可以是函数,也可以是简单的值。当调用对象的方法时,“this”指向包含被调用方法的对象。
在下面的例子中,您可以看到 this 值如何根据执行上下文而不同。
“this” 与 call 或 apply 方法
JavaScript 中的函数也是一种特殊的对象。每个函数都拥有call
、bind
和apply
方法。这些方法可用于将 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
的上下文更改为 的上下文。innerDisplay
Dog
更多,更多,更多……
- https://www.tutorialsteacher.com/javascript/new-keyword-in-javascript
- https://medium.com/quick-code/understanding-the-this-keyword-in-javascript-cb76d4c7c5e8
- https://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/
- http://ryanmorr.com/understanding-scope-and-context-in-javascript/
- https://medium.com/@marjanrab/javascript-scope-context-and-this-under-the-hood-43c32033c9f9
- https://scotch.io/tutorials/understanding-scope-in-javascript
- https://medium.com/javascript-in-plain-english/hello-javascript-this-bb97c54f0823
*最初于 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