作用域
js的作用域有两种,全局作用域和局部作用域,对于 var 声明的变量,只有 function才可以为他创建局部作用域,对于let 声明的变量,支持块级作用域 { } 生成
变量提升
什么是变量提升?
在编译过程,将所有变量声明和函数声明提升到作用域顶部
JavaScript的源代码在运行的时候,会经过两个阶段:编译和执行。而且,编译阶段往往就在执行阶段的前几微秒甚至更短的时间内。
在编译的过程,会经历词法分析,语法分析,生成中间代码等过程,变量提升发生在编译阶段,生成可执行的中间代码。
提升原理
LHS查询
在编译的过程中,先将标识符和函数声明给提升到其对应的作用域的顶端。标识符解析的时候,会进行LHS查询,在LHS查询的时候,如果标识符一直找不到声明的位置,那么最终就会在全局环境生成一个全局变量。 LHS : 指的是赋值操作的左端。
提升案例
补齐声明
在解析过程中,如果找不到声明,最终在全局环境生成一个全局变量
function test(){message = 'hi'}test()console.log(message)
还原编译后代码
var messagefunction test(){message = 'hi'}test() //message = 'hi'console.log(message)执行hi
函数只提升声明式
函数提升,只会提升声明式函数,而不会提升函数表达式
f();fn();//fn is not a function//函数表达式var fn = function(){console.log(1)}//函数声明function f(){console.log(0)}
编译结果
//函数声明function f(){console.log(0)}var fn = undefined;f();fn();fn = function(){console.log(1)}
所以执行会报错
0Uncaught TypeError: fn is not a functionat <anonymous>:2:1
再看下这个例子
function test() {function f3(a) {f = a;console.log("1");};}console.log(typeof f3); // undefined
重复声明优先 function
同名声明function会覆盖var声明的
add();console.log(typeof add);function add(){console.log('加++');}var add;
编译
var add;function add(){console.log('加++');}add();console.log(typeof add);

