变量提升问题笔记
Posted усил
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了变量提升问题笔记相关的知识,希望对你有一定的参考价值。
提升
这里我们不考虑 ES6 这部分的知识点
前期知识准备
1、首先先理解 javascript 是如何执行代码的
JavaScript 是动态语言,在执行代码时要先进行编译。
-
第一部分是编译代码(主要是全局声明函数和变量),并且生成代码(将用户的代码生成符合 JavaScript 正确顺序执行,具体顺序后面有细讲)
-
第二部分是执行代码(执行函数或变量赋值)
2、了解 JavaScript 中的 引擎、编译器、作用域三者的作用及区别
- 引擎:从头到尾负责整个 JavaScript 程序的编译及执行过程。
- 编译器:负责语法分析及代码生成
- 作用域:负责收集并维护有所有声明的标识符(变量)组成的一系列查询,并实施非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
上才艺
// 调用函数
fun1();
// 声明全局变量
var g = 2;
// 函数声明
function fun1() {
console.log(b);
var b = 0;
console.log(b);
console.log(g);
}
-
补充:
-
局部作用域 指的是函数内部(函数分很多种,这里是所有函数)
-
var b =2 在程序中是被拆分成 var b b =2
-
函数声明的优先级要高于变量
-
var a = 10; function a() {} console.log(typeof a) // number
-
函数可以分为函数声明,函数表达式,立即执行函数等,但唯独函数声明会提升。
-
-
-
第一步:程序会被转成 JavaScript 内部认为正确的顺序
-
function fun1() { var b; console.log(b); // undefined b = 0; console.log(b); // 0 console.log(g); // undefined } var g; fun1(); g = 2;
-
依据以下几点来判断其顺序
- 从上往下(全局)看:看到变量声明或函数表达式时将其提到最前面。且函数声明的优先级要高于变量(可以理解为在当前作用域中函数表达式始终是在最前面的)
- 接下来就是调整局部作用域中的函数表达式和变量声明,依据跟上面一样。
-
-
第二步:将全局及局部变量和函数告诉作用域,作用域会根据信息给变量和函数创建相对应的空间
-
如何创建依据以下几点
- 前提:变量和函数在全局下。直接在顶级作用域声明变量和函数
- 局部(函数)下:在局部作用域下声明变量和函数。
-
-
第三步:代码执行阶段,就是按第一步生成的顺序从上到下来执行。
在上面的小例子中,在 JavaScript 执行被我分为三部分。真正执行是俩部分(编译阶段和执行阶段),只不过在编译阶段要经历第一步和第二步。为了方便理解,我把它细分出来。
执行阶段
具体看下面代码
(function() {
var a = b = 5;
})()
console.log(b);
console.log(a);
根据上面的例子,很容易可以得到真正的执行顺序
(function() {
var a;
a = b;
b = 5;
})();
console.log(b); // 5
console.log(a); // Uncaughte ReferenceError: a is not defined
这里跟第一个案例的区别在于执行阶段
在 a = b 赋值阶段,首先
- 引擎会问作用域在立即执行函数中是否存在 变量 b ;
- 作用域在该作用域(立即执行函数)下找变量 b,若没有找到。此时作用域会接着往上一层作用域找变量 b 直到找到顶级作用域还没有找到,直接告诉引擎编译器没有声明该变量。
- 引擎接收到信息后,执行 a = b 由于程序中并没有存在变量 b , 故执行 console.log(a); 会报错 Uncaughte ReferenceError: a is not defined
在 b = 5 这个阶段跟上面是不一样,在赋值前变量已经被创建了,只不过是在全局下声明,故在 console.log(b) 输出结果为 5
这里就涉及到 RHS 和 LHS 具体看 这里
以上是关于变量提升问题笔记的主要内容,如果未能解决你的问题,请参考以下文章