In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces JavaScript implementation context example analysis, the article is very detailed, has a certain reference value, interested friends must read!
What is the execution context?
JavaScript execution environment is very important, when JavaScript code is on line, it will be preprocessed into one of the following cases:
Global code -The default environment in which the code is executed for the first time.
Function code -Whenever execution flow enters function body.
Eval code -Text to be executed inside eval function.
You can read a lot about scope online, but to make things easier, let's think of the term "execution context" as the environment or scope in which the current code runs. Next let's look at a code example that contains both global and function / local contexts.
There is nothing special here, we have a global context represented by a purple border, and 3 different function contexts represented by green, blue, and orange borders. There can only be 1 global context, accessible from any other context in the program.
You can have any number of function contexts, and each function call creates a new context, creating a private scope where nothing declared inside the function is directly accessible from outside the scope of the current function. In the example above, a function can access variables declared outside of its current context, but an external context cannot access variables or functions declared within it. Why is this happening? How exactly does this code work?
Execution Context Stack
JavaScript interpreters in browsers are implemented as a single thread. In practice this means that only one thing can be done at a time in the browser, with other actions or events queued in what is known as the execution stack. The following is an abstract view of a single-threaded stack:
We already know that when a browser loads a script for the first time, it defaults to global context execution. If a function is called in global code, the sequential flow of the program enters the called function, creating a new execution context and pushing it to the top of the execution stack.
If another function is called within the current function, the same thing happens. The execution flow of the code goes into an internal function that creates a new execution context that is pushed to the top of the existing stack. The browser will always execute the current execution context at the top of the stack, and once the function finishes executing the current execution context, it pops off the top of the stack, returning control to the next context in the current stack. The following example shows the execution stack of recursive functions and programs:
(function foo(i) { if (i === 3) { return; } else { foo(++i); }}(0));
代码简单地调用自身3次,并将i的值递增1。每次调用函数foo时,都会创建一个新的执行上下文。 一旦上下文完成执行,它就会弹出堆栈并且讲控制返回到它下面的上下文,直到再次达到全局上下文。
关于执行堆栈execution stack有5个关键要点:
单线程。
同步执行。
一个全局上下文。
任意多个函数上下文。
每个函数调用都会创建一个新的执行上下文execution context,什至是对自身的调用。
执行上下文的细节
所以我们现在知道每次调用一个函数时,都会创建一个新的执行上下文。 但是,在JavaScript解释器中,对执行上下文的每次调用都有两个阶段:
创建阶段 [调用函数时,但在执行任何代码之前]:
创建作用域链。
创建变量,函数和参数。
确定"this"的值。
激活/代码执行阶段:
分配值,引用函数和解释/执行代码。
可以将每个执行上下文在概念上表示为具有3个属性的对象:
executionContextObj = { 'scopeChain': { /* variableObject + 所有父执行上下文的variableObject */ }, 'variableObject': { /* 函数实参/形参,内部变量和函数声明 */ }, 'this': {}}
激活对象/变量对象 [AO/VO]
在调用该函数,并且在实际执行函数之前,会创建这个executionContextObj。 这被称为第1阶段,即创造阶段。 这时解释器通过扫描函数传递的实参或形参、本地函数声明和局部变量声明来创建executionContextObj。 此扫描的结果将成为executionContextObj中的variableObject。
以下是解释器如何预处理代码的伪代码概述:
1.找一些代码来调用一个函数。
2.在执行功能代码之前,创建执行上下文。
3.进入创建阶段:
①初始化作用域链。
②创建variable object:
创建arguments object,检查参数的上下文,初始化名称和值并创建引用副本。
扫描上下文以获取函数声明:
对于找到的每个函数,在variable object中创建一个属性,该属性是函数的确切名称,该属性存在指向内存中函数的引用指针。
如果函数名已存在,则将覆盖引用指针值。
扫描上下文以获取变量声明:
对于找到的每个变量声明,在variable object中创建一个属性作为变量名称,并将该值初始化为undefined。
如果变量名称已存在于variable object中,则不执行任何操作并继续扫描。
③确定上下文中"this"的值。
4.激活/执行阶段:
在上下文中运行/解释函数代码,并在代码逐行执行时分配变量值。
我们来看一个例子:
function foo(i) { var a = 'hello'; var b = function privateB() { }; function c() { }}foo(22);
在调用foo(22)时,创建阶段如下所示:
fooExecutionContext = { scopeChain: { ... }, variableObject: { arguments: { 0: 22, length: 1 }, i: 22, c: pointer to function c() a: undefined, b: undefined }, this: { ... }}
如你所见,创建阶段处理定义属性的名称,而不是为它们赋值,但正式的形参/实参除外。创建阶段完成后,执行流程进入函数,激活/代码执行阶段在函数执行完毕后如下所示:
fooExecutionContext = { scopeChain: { ... }, variableObject: { arguments: { 0: 22, length: 1 }, i: 22, c: pointer to function c() a: 'hello', b: pointer to function privateB() }, this: { ... }}
关于hoisting
你可以找到许多使用JavaScript定义术语hoisting的在线资源,解释变量和函数声明被hoisting到其函数范围的顶部。 但是没有人能够详细解释为什么会发生这种情况,掌握了关于解释器如何创建激活对象的新知识,很容易理解为什么。 请看下面的代码示例:
(function() { console.log(typeof foo); // function pointer console.log(typeof bar); // undefined var foo = 'hello', bar = function() { return 'world'; }; function foo() { return 'hello'; }}());
我们现在可以回答的问题是:
为什么我们可以在声明foo之前就能访问?
如果我们理解了创建阶段,就知道在激活/代码执行阶段之前已经创建了变量。因此,当函数流开始执行时,已经在激活对象中定义了foo。
Foo被声明两次,为什么foo显示为function而不是undefined或string?
即使foo被声明两次,我们通过创建阶段知道函数在变量之前就被创建在激活对象上了,而且如果激活对象上已经存在了属性名称,我们只是绕过了声明这一步骤。
因此,首先在激活对象上创建对函数foo()的引用,并且当解释器到达var foo时,我们已经看到属性名称foo存在,因此代码不执行任何操作并继续处理。
为什么bar未定义?
bar实际上是一个具有函数赋值的变量,我们知道变量是在创建阶段被创建的,但它们是使用undefined值初始化的。
希望到这里你已经能够很好地掌握了JavaScript解释器如何预处理你的代码。 理解执行上下文和堆栈可以让你了解背后的原因:为什么代码预处理后的值和你预期的不一样。
你认为学习解释器的内部工作原理是多此一举还是非常必要的呢? 了解执行上下文阶段是否能够帮你你写出更好的JavaScript呢?
以上是"JavaScript中执行上下文的示例分析"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.