这是迄今为止最重要的主题之一,它让您瞥见其他关键主题,例如作用域、词法作用域、闭包和提升,并且很容易了解JavaScript的真正工作原理。有趣的。至此,在代码编辑器(Vs代码)中编写的每一行乱七八糟的代码都运行在我们现在要讨论的这个执行上下文中。坐下来,放松,收拾好你的好东西,因为我会让你看到的。在JavaScript中,一切都发生在执行上下文中,我指的是一切。您可以将其视为评估和执行JavaScript代码的环境。每当您的浏览器与任何JavaScript代码交叉路径时,浏览器的JavaScript引擎都会创建一个特殊的环境来处理此JavaScript代码的转换和执行。该环境称为执行上下文。执行上下文包含当前正在运行的代码以及有助于其执行的所有内容。执行上下文的类型当您在浏览器中运行脚本时,javascript引擎会创建不同类型的执行上下文。全局执行上下文(GEC)当您第一次运行脚本或您的代码不在任何函数内时,它被放置在全局执行上下文(GEC)中。在这里,每当JavaScript引擎接收到脚本文件时,它首先创建一个默认的执行上下文,也就是我们所说的全局执行上下文(GEC)。它是一个基本/默认的执行上下文,所有不在函数内的代码都将被执行。注意:每个JavaScript文件只有一个GEC函数执行上下文(FEC)每当您的JavaScript引擎遇到函数调用时,它都会在全局执行上下文中创建一种称为函数执行上下文的不同类型的EC,以评估和执行内部编写的代码那个功能。每个函数调用都有自己的FEC(即使您多次调用同一个函数),因此在脚本运行时可以有多个FEC。它们是如何创建的?执行上下文创建现在分两个阶段进行:创建阶段执行阶段1,创建阶段在此阶段,创建一个执行上下文对象(ECO),其中包含我们的代码在运行时(执行阶段)/data使用的重要信息。此对象(ECO)中的属性在三个不同阶段中设置和定义。创建一个可变对象(VO)。创建作用域链。给这个关键字一个值。阶段1:变量对象的创建变量对象就像是在执行上下文中创建的容器,它以键值对(不是函数表达式)的形式存储变量和函数声明。在GEC中,每个用var关键字声明的变量都会在变量对象中添加一个指向该变量的属性并将其值设置为undefined,用let或const声明的变量得到一个未初始化的值,而在函数声明中,会在变量对象中添加一个属性指向函数的变量对象,所有函数声明都将在VO中存储和访问,甚至在代码开始运行之前。在FEC中,不会创建此变量对象,而是构造一个名为“argument”的类数组对象,其中包括提供给函数的所有参数。这种甚至在代码执行之前就在内存中存储变量和函数(声明)的方法就是我们所说的提升。第2阶段:创建作用域链在JavaScript中,作用域是一种理解一段代码对脚本的其他域的可访问性的方式。每个函数执行上下文都会创建它的范围,可以将其视为环境或空间,并且可以通过称为范围的过程访问它定义的变量和函数。现在,当一个函数(比如X())在另一个函数(比如Y())中定义时,这个内部函数X()将可以访问变量,并且在外部函数Y()中定义的其他函数也可以访问到外部函数的代码,但事情不止于此,它还可以访问其父元素的代码等等,直到GCE,这种行为就是我们所说的词法作用域,但反之则不然。这种范围的概念在JavaScript中引起了一种称为闭包的相关现象,其中即使在外部函数完成执行后,内部函数也可以访问与外部函数关联的代码……它已经死了,消失了,很久以前就消失了。让我们再看一个例子来理解作用域链。leta=10;functionfirst(){letb=20;第二();functionsecond(){让c=30;控制台日志(a+b+c);}}第一的();//outputis60这里变量a和b没有在函数second()中定义,它只能访问定义在自己作用域(本地作用域)的变量c,但是因为词法作用域,它可以访问它所在的函数as以及它的父母。所以当你运行这段代码时,JavaScript引擎将无法找到变量a或b,因此它将首先沿着执行上下文链找到b并解析它,因为它已在函数范围内成功找到它first(),resolving继续寻找变量a后,JavaScript引擎会去到这个变量的全局执行上下文并解析。JavaScript引擎将不同的执行上下文链接起来的过程,或者我们可以说遍历执行上下文的范围以解析变量或函数调用/调用,称为作用域链接。第三阶段:设置“this”关键字的值在javascript中,this关键字指的是执行上下文所属的范围。在GEC中,这是指一个全局对象,在浏览器的情况下是一个窗口对象。因此,在函数声明中,用“var”关键字初始化的变量分别作为方法和属性赋值给这个全局对象。所以varx="hello"functiony(){console.log("hello")}与window.x="hello"window.y=()=>{console.log("hello")}相同但在FEC的情况下,它不会创建“this”关键字,而是可以访问定义它的环境的关键字。执行阶段在执行上下文的这个阶段,我们的代码开始执行,并在执行后从执行堆栈或调用堆栈中弹出,我们将在本文后面介绍。截至目前,Variable对象包含值为undefined和uninitialized的变量,具体取决于变量是分别使用var关键字还是let/const声明的。JavaScript引擎再次读取EC中的代码,用它们的实际值更新这些变量。然后代码被解析、翻译,最后是执行栈(调用栈)你有没有想过JavaScript引擎是如何在脚本运行时跟踪它创建的各种EC的所有这些创建和删除的?答案是执行堆栈或调用堆栈。“JavaScript是一种同步的、单线程的语言”单线程意味着它一次只能执行一个任务,一次只能执行一行代码,而同步意味着这些任务的执行是按照特定的顺序发生的。因此,当JavaScript引擎读取脚本时,它会创建不同的执行上下文并将它们存储在称为调用堆栈或执行堆栈的堆栈数据结构中。varname="Victor";functionfirstFunc(){vara="嗨!";第二函数();console.log(`${a}${name}`);}functionsecondFunc(){varb="嘿!";第三();console.log(`${b}${name}`);}functionthirdFunc(){varc="Hello!";console.log(`${c}${name}`);}first();当脚本在浏览器中加载时,浏览器的JS引擎首先创建一个我们上面详述的默认特殊环境,即全局执行上下文,并将其推送到这个执行堆栈。稍后,当JS引擎找到执行文件的函数调用时,它会为其创建一个单独的函数执行上下文,如下图所示(步骤2),并将其压入现有默认GEC之上的堆栈。在执行firstFunc()时,它遇到对secondFunc()的调用,它暂停firstFunc()的执行并创建另一个FEC并压入firstFunc()FEC顶部的堆栈,然后再次为thirdFunc()FEC指定。最上面的EC会被JS引擎先执行,当执行完成后,它会从栈中弹出并开始执行上一个活动EC下面的EC,如上图所示,直到到达GEC。结论执行上下文是JavaScript的核心,理解它很重要,因为它可以帮助您正确理解其他主要概念。希望本文对您有所帮助,如果您觉得有用,请分享给您的朋友,最后,感谢您的阅读,祝您编程愉快!
