This article brings you relevant knowledge about javascript variable promotion. What is variable promotion and why there is variable promotion? Let’s take a look at it together. I hope it will be helpful to everyone.
Related recommendations: javascript learning tutorial
Let’s look at the code first. What do you think the following code outputs? what's the result?
showName() console.log(myname) var myname = '极客时间' function showName() { console.log('函数showName被执行'); }
Programmers who have used JavaScript development should know that JavaScript is executed in order. If we understand it according to this logic, then:
However, the actual execution result is not like this, as shown below:
The first line outputs "function showName is executed", and the second line outputs "undefined", which is the same as The sequential execution as imagined earlier is a bit different!
Through the above execution results, you should already know that functions or variables can be used before they are defined. So if you use undefined variables or functions, can the JavaScript code continue to execute? In order to verify this, we can delete the definition of the variable myname in line 3, as follows:
showName() console.log(myname) function showName() { console.log('函数showName被执行'); }
Then when this code is executed again, the JavaScript engine will report an error, and the result is as follows:
Judging from the execution results of the above two pieces of code, we can draw the following three conclusions:
The first conclusion is easy to understand, because the variable is not defined, so when the JavaScript code is executed, the variable cannot be found, so JavaScript will throw an error.
But for the second and third conclusions, it is quite puzzling:
To explain these two issues, you need to first understand what variable hoisting is.
But before introducing variable promotion, let’s first look at the following code to see what declaration and assignment in JavaScript are.
var myname = '极客时间'
You can think of this code as consisting of two lines of code:
var myname //声明部分 myname = '极客时间' //赋值部分
As shown below:
The above is the declaration and Assignment, then let’s take a look at the declaration and assignment of functions, combined with the following code:
function foo(){ console.log('foo') } var bar = function(){ console.log('bar') }
The first function foo is a complete function declaration, which means that there is no assignment operation involved; The two functions first declare the variable bar, and then assign function(){console.log('bar')} to bar. For an intuitive understanding, you can refer to the following picture:
Okay, now that we understand the declaration and assignment operations, we can now talk about what variable promotion is.
The so-called variable promotion refers to the "behavior" in which the JavaScript engine promotes the declaration part of variables and the declaration part of functions to the beginning of the code during the execution of JavaScript code. After the variable is promoted, a default value will be set for the variable. This default value is the familiar undefined.
Let’s simulate the implementation:
/* * 变量提升部分 */// 把变量 myname提升到开头,// 同时给myname赋值为undefinedvar myname = undefined// 把函数showName提升到开头function showName() { console.log('showName被调用');}/* * 可执行代码部分 */showName()console.log(myname)// 去掉var声明部分,保留赋值语句myname = '极客时间'
In order to simulate the effect of variable promotion, we have made the following adjustments to the code, as shown below:
As can be seen from the picture, two main adjustments have been made to the original code:
通过这两步,就可以实现变量提升的效果。你也可以执行这段模拟变量提升的代码,其输出结果和第一段代码应该是完全一样的。
通过这段模拟的变量提升代码,相信你已经明白了可以在定义之前使用变量或者函数的原因——函数和变量在执行之前都提升到了代码开头。
从概念的字面意义上来看,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,正如我们所模拟的那样。但,这并不准确。实际上变量和函数声明在代码里的位置是不会改变的,而且是在编译阶段被 JavaScript 引擎放入内存中。对,你没听错,一段 JavaScript 代码在执行之前需要被 JavaScript 引擎编译,编译完成之后,才会进入执行阶段。大致流程你可以参考下图:
那么编译阶段和变量提升存在什么关系呢?
为了搞清楚这个问题,我们还是回过头来看上面那段模拟变量提升的代码,为了方便介绍,可以把这段代码分成两部分。
第一部分:变量提升部分的代码。
var myname = undefined function showName() { console.log('函数showName被执行'); }
第二部分:执行部分的代码。
showName() console.log(myname) myname = '极客时间'
下面我们就可以把 JavaScript 的执行流程细化,如下图所示:
从上图可以看出,输入一段代码,经过编译后,会生成两部分内容:执行上下文(Execution context)和可执行代码。
执行上下文是 JavaScript 执行一段代码时的运行环境,比如调用一个函数,就会进入这个函数的执行上下文,确定该函数在执行期间用到的诸如 this、变量、对象以及函数等。
关于执行上下文的细节,我会在下一篇文章《08 | 调用栈:为什么 JavaScript 代码会出现栈溢出?》做详细介绍,现在你只需要知道,在执行上下文中存在一个变量环境的对象(Viriable Environment),该对象中保存了变量提升的内容,比如上面代码中的变量 myname 和函数 showName,都保存在该对象中。
你可以简单地把变量环境对象看成是如下结构:
VariableEnvironment: myname -> undefined, showName ->function : {console.log(myname)
了解完变量环境对象的结构后,接下来,我们再结合下面这段代码来分析下是如何生成变量环境对象的。
showName() console.log(myname) var myname = '极客时间' function showName() { console.log('函数showName被执行'); }
我们可以一行一行来分析上述代码:
这样就生成了变量环境对象。接下来 JavaScript 引擎会把声明以外的代码编译为字节码,至于字节码的细节,我也会在后面文章中做详细介绍,你可以类比如下的模拟代码:
showName() console.log(myname) myname = '极客时间'
好了,现在有了执行上下文和可执行代码了,那么接下来就到了执行阶段了。
JavaScript 引擎开始执行“可执行代码”,按照顺序一行一行地执行。下面我们就来一行一行分析下这个执行过程:
VariableEnvironment: myname -> "极客时间", showName ->function : {console.log(myname)
好了,以上就是一段代码的编译和执行流程 。
现在你已经知道了,在执行一段 JavaScript 代码之前,会编译代码,并将代码中的函数和变量保存到执行上下文的变量环境中,那么如果代码中出现了重名的函数或者变量,JavaScript 引擎会如何处理?
我们先看下面这样一段代码:
function showName() { console.log('极客邦'); } showName(); function showName() { console.log('极客时间'); } showName();
在上面代码中,我们先定义了一个 showName 的函数,该函数打印出来“极客邦”;然后调用 showName,并定义了一个 showName 函数,这个 showName 函数打印出来的是“极客时间”;最后接着继续调用 showName。那么你能分析出来这两次调用打印出来的值是什么吗?
我们来分析下其完整执行流程:
综上所述,一段代码如果定义了两个相同名字的函数,那么最终生效的是最后一个函数。
好了,今天就到这里,下面我来简单总结下今天的主要内容:
相关推荐:javascript学习教程
The above is the detailed content of JavaScript execution mechanism - variable promotion (detailed examples). For more information, please follow other related articles on the PHP Chinese website!