JavaScript 究竟如何工作?
听说过 JavaScript,但不懂其基础知识?不知道幕后发生了什么?面试时遇到困难?别担心。这篇文章将带你了解 JavaScript 的基本概念。这些概念在你的日常工作中可能用得到,也可能用不到,但如果你对 JavaScript 充满好奇,并想深入了解它,我相信你会对它充满兴趣。这篇文章将涵盖 JS 最基础的主题之一——执行上下文。废话不多说,让我们开始吧。
您听说过“执行上下文”吗?
执行上下文是 JS 中最基本的概念之一。我这样解释一下。
JS 中的一切都发生在执行上下文中。
让我们借助一个例子来理解这一点。下面的代码求给定数字的平方。
当我们运行一个 JS 程序时,会创建一个执行上下文。这个过程涉及两个阶段。第一个阶段称为内存创建阶段,第二个阶段称为代码执行阶段。
在内存创建阶段,JS 解析程序并查找变量和函数定义。对于变量,会分配一个名为undefined的特殊关键字;对于函数,JS 会存储整个函数定义的副本。(查看图表)。
注意:undefined不是一个值,它是 JS 中使用的特殊关键字,表示变量未定义或未分配任何值。
第二阶段是代码执行阶段。在这个阶段,JS 从头开始,以同步的方式(一行一行地)执行。
注意:这可能是你面试时遇到的第一个问题之一。“JavaScript 是同步语言还是异步语言?”我想你现在应该知道答案了。
在第 1 行,“n”的值设置为 10,因此 JS 删除了关键字 undefined,并将值设置为 10。现在,控制权转到下一个代码块。由于这是一个函数定义,这里没有代码执行,因此 JS 跳过函数定义并将控制权移至第 8 行。一旦 JS 遇到函数调用 [ square(5) ],它就会创建一个新的执行上下文,如下所示。
现在,执行上下文的整个过程针对该函数调用重复进行。让我们看看函数块是如何执行的。
在内存创建阶段,我们将有两个变量:“number”(函数参数)和“ans”(局部变量)。这两个变量的值都设置为“undefined”。在当前执行上下文的第二阶段,JS 从该函数声明的第一行开始执行。由于我们在函数调用中传递了 5 作为参数,因此 5 被赋值给变量 number。现在,控制权转到下一行。
在下一行,JS 执行了该行的 [ number * number ] 部分,并将此操作的结果(即 25)存储在变量“ans”中。现在下一行有一个关键字“return”。一旦 JS 遇到“return”关键字,它就会将控制权移回父执行上下文。由于我们返回的是“ans”的值,因此返回值 25 并将其存储在变量“squareOf5”中。现在记住这一点。
当控制移回到函数调用的位置时,新创建的执行上下文将被删除。
看看下面的图表。
现在控制转到下一行,这又是一个函数调用,并且执行上下文的整个过程再次重复。
JS 如何跟踪这些执行上下文?
这是通过调用栈或执行栈来实现的。它类似于普通的栈,但主要用于跟踪执行上下文。
当 JS 引擎首次遇到脚本时,它会创建一个全局执行上下文(GEC),并将其推送到调用栈。在 GEC 的代码执行阶段,每当 JS 引擎遇到函数调用时,它都会创建一个新的执行上下文并将其推送到调用栈。
引擎执行执行上下文位于堆栈顶部的函数。当该函数执行完成后,其执行堆栈将从堆栈中弹出,并继续执行脚本的其余部分。
最后的想法
我希望现在你已经对执行上下文有了很好的理解。如果要我用简单的语言解释执行上下文的重要性,我可以说执行上下文是 JS 的心脏。
我还要说一下,我还没有深入探讨,但有很多概念可以涵盖。
感谢您阅读本文。请在评论区分享您的想法。
参考:
-
JavaScript 代码如何执行?& Akshay Saini 的调用堆栈https://www.youtube.com/watch?v=iLWTnMzWtj4
-
Sukhjinder Arora 的文章
https://blog.bitsrc.io/understand-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0