Home > Article > Web Front-end > Deep understanding of how the JavaScript engine executes JS code
This article brings you relevant knowledge about javascript, which mainly introduces the related issues of how the js engine executes js code. When the js engine executes js code, it will also start from top to bottom. Lexical analysis, syntax analysis, semantic analysis and other processing are performed below, and AST is generated after the code analysis is completed. I hope it will be helpful to everyone.
Related recommendations: javascript tutorial
We probably often hear "execution environment", "Deep understanding of how the JavaScript engine executes JS code", "prototype" (chain)", "execution context", etc., what do they describe?
We know that js is a weakly typed language, and the variable type is determined only at runtime. When the js engine executes the js code, it will also perform lexical analysis, grammatical analysis, semantic analysis and other processes from top to bottom, and after the code parsing is completed Generate AST (Abstract Syntax Tree), and finally generate machine code that the CPU can execute based on the AST and execute it.
In addition, the JS engine will also perform other processing when executing the code. For example, there are two stages in V8:
This This introduces two concepts: "execution context" and "Deep understanding of how the JavaScript engine executes JS code chain".
From the above we can know: when js code executes a piece of executable code, a corresponding execution context will be created.
First of all, there is a concept corresponding to executable code in js: "execution environment" - global environment, function environment and eval
.
Secondly, for each execution context, there are three important properties:
Let’s look at two pieces of code:
var Deep understanding of how the JavaScript engine executes JS code="global Deep understanding of how the JavaScript engine executes JS code";function checkDeep understanding of how the JavaScript engine executes JS code(){ var Deep understanding of how the JavaScript engine executes JS code="local Deep understanding of how the JavaScript engine executes JS code"; function f(){ return Deep understanding of how the JavaScript engine executes JS code; } return f();}checkDeep understanding of how the JavaScript engine executes JS code();
var Deep understanding of how the JavaScript engine executes JS code="global Deep understanding of how the JavaScript engine executes JS code";function checkDeep understanding of how the JavaScript engine executes JS code(){ var Deep understanding of how the JavaScript engine executes JS code="local Deep understanding of how the JavaScript engine executes JS code"; function f(){ return Deep understanding of how the JavaScript engine executes JS code; } return f;}checkDeep understanding of how the JavaScript engine executes JS code()();
What will they print?
Why? The answer is that their execution context stacks are different!
What is the "execution context stack"?
When executing an executable code, preparations will be made in advance. The "preparations" here are professionally called "execution context". But with the increase in executable code such as functions, how to manage so many execution contexts? So the JS engine created the concept of execution context stack.
We can completely use an array to simulate its behavior (there is always a global execution context globalContext at the bottom of the stack)
We define an EStack, first
EStack=[globalContext];
and then simulate the first Code snippet:
EStack.push(<checkdeep understanding of how the javascript engine executes js code> functionContext);EStack.push(<f> functionContext);EStack.pop();EStack.pop();</f></checkdeep>
And the second code snippet is like this:
EStack.push(<checkdeep understanding of how the javascript engine executes js code> functionContext);EStack.pop();EStack.push(<f> functionContext);EStack.pop();</f></checkdeep>
The reason is that you may need to study the concept of "closure" first!
By the way, how to achieve "long-term data saving" in "front-end modularization"?
cache? No. Closure!
First of all, Deep understanding of how the JavaScript engine executes JS code refers to the area in the program where variables are defined. The Deep understanding of how the JavaScript engine executes JS code specifies how to find the variable, which determines the access rights of the currently executing code to the variable.
There are two types of Deep understanding of how the JavaScript engine executes JS code: static Deep understanding of how the JavaScript engine executes JS code and dynamic Deep understanding of how the JavaScript engine executes JS code.
The static Deep understanding of how the JavaScript engine executes JS code used by JS is also called "lexical Deep understanding of how the JavaScript engine executes JS code". The Deep understanding of how the JavaScript engine executes JS code of a function is determined when the function is defined.
From the above, variables in the lexical Deep understanding of how the JavaScript engine executes JS code will have a certain Deep understanding of how the JavaScript engine executes JS code during the compilation process. This Deep understanding of how the JavaScript engine executes JS code is the "current execution context". After ES5 we use "lexical environment" instead of Deep understanding of how the JavaScript engine executes JS code to describe the execution context. The lexical environment consists of two members:
Let’s still look at an example:
var Deep understanding of how the JavaScript engine executes JS code=1;function foo(){ console.log(Deep understanding of how the JavaScript engine executes JS code);}function bar(){ var Deep understanding of how the JavaScript engine executes JS code=2; foo();}bar();
Looking back at the above definition, what should be printed?
Let us analyze the execution process:
Execute the foo() function, first find whether there is a local variable Deep understanding of how the JavaScript engine executes JS code inside the foo function. If not, will look for the code of the upper layer based on the position when it was defined, that is, Deep understanding of how the JavaScript engine executes JS code=1. So the result will be printed as 1.
Of course it is not so simple and can be summarized. You can analyze it from the perspective of execution context.
上面我们说了词法环境(作用域)的两个组成。再结合执行上下文,我们不难发现:通过外部词法环境的引用,作用域可以顺着栈层层拓展,建立起从当前环境向外延伸的一条链式结构。
再来看一个例子:
function foo(){ console.dir(bar); var a=1; function bar(){ a=2; }}console.dir(foo);foo();
由静态作用域,全局函数foo创建了一个自身对象的 [[Deep understanding of how the JavaScript engine executes JS code]]
属性
foo[[Deep understanding of how the JavaScript engine executes JS code]]=[globalContext];
而当我们执行foo()时,也会先后进入foo函数的定义期和执行期。在foo函数的定义期时,函数bar的 [[Deep understanding of how the JavaScript engine executes JS code]]
将会包含全局内置Deep understanding of how the JavaScript engine executes JS code和foo的内置Deep understanding of how the JavaScript engine executes JS code
bar[[Deep understanding of how the JavaScript engine executes JS code]]=[fooContext,globalContext];
这证明了这一点:“JS会通过外部词法环境引用来创建变量对象的一个作用域链,从而保证对执行环境有权访问的变量和函数的有序访问。”
让我们再回头看看执行上下文中的那道题,在前面我们说了它们有什么不同,这里说下为什么它们相同地打印了“local Deep understanding of how the JavaScript engine executes JS code”:还是那句话“JS采用的是词法作用域,函数的作用域取决于函数创建的位置” —— JS函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量Deep understanding of how the JavaScript engine executes JS code一定是指局部变量,不管何时何地执行 f() ,这种绑定在执行 f() 时依然有效。
当某个变量无法在自身词法环境记录中找到时,可以根据外部词法环境引用向外层进行寻找,直到最外层的词法环境中外部词法环境引用为null
。
与此相似的是“对象中基于原型链的查找”:
__proto__
为null)为止它们的区别也显而易见:原型链是通过 prototype 属性建立对象继承的链接;而作用域链是指内部函数能访问到外部函数的闭包。不管直接还是间接,所有函数的作用域链最终都链接到全局上下文。
相关推荐:javascript学习教程
The above is the detailed content of Deep understanding of how the JavaScript engine executes JS code. For more information, please follow other related articles on the PHP Chinese website!