一、什么是变量提升?
JavaScript中,函数和变量的声明总是会被悄悄地“提升”到各自作用域的最顶部。
二、为什么会出现“提升”现象?
我们直觉上会认为JavaScript代码在执行时期是由上到下一行一行地执行,实际上并不完全正确。
先来看个demo,验证下这一说法:
a = 2;
var a;
console.log(a);
很多开发会认为输出是undefined。但是,真正代码执行的输出结果是2。上述情况推翻了JavaScript代码由上到下逐行执行的说法。
为了搞明白这个问题,我们需要了解JavaScript在运行时经历了哪些阶段?
任何JavaScript代码片段主要经历了2个阶段:预编译和执行。
1、预编译阶段:
任何JavaScript代码片段在执行前都要进行预编译(通常就在执行前),预编译所占用的时间仅仅是几微秒(甚至更短),所以我们开发人员基本感知不到这一阶段。
预编译阶段会经历三个步骤:
分词/词法分析(Tokenizing/Lexing)
这个过程会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代 码块被称为词法单元(token)。例如,考虑程序var a = 2;。这段程序通常会被分解成 为下面这些词法单元:var、a、=、2 、;。空格是否会被当作词法单元,取决于空格在 这门语言中是否具有意义。
解析/语法分析(Parsing)
这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法 结构的树。这个树被称为“抽象语法树”(Abstract Syntax Tree,AST)。
var a = 2; 的抽象语法树中可能会有一个叫作 VariableDeclaration 的顶级节点,接下 来是一个叫作 Identifier(它的值是 a)的子节点,以及一个叫作AssignmentExpression的子节点。AssignmentExpression 节点有一个叫作 NumericLiteral(它的值是2)的子节点。
代码生成
将 AST 转换为可执行代码的过程称被称为代码生成。这个过程与语言、目标平台等息 息相关。抛开具体细节,简单来说就是有某种方法可以将 var a = 2; 的 AST 转化为一组机器指 令,用来创建一个叫作a的变量(包括分配内存等),并将一个值储存在 a 中。
简单来讲,预编译阶段主要执行了两个任务:
1)声明所有var变量(初始值为undefined);
2)解析定义式函数语句。
也就是说变量”提升“实际上是在JavaScript预编译阶段完成的。
2、执行阶段:
由上至下逐行执行解析js代码,根据表达式=+-*++—...修改预编译的值。
链接:https://juejin.im/post/5dac1a236fb9a04dfd267d55
|
|