变量提升问题笔记

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 具体看 这里

以上是关于变量提升问题笔记的主要内容,如果未能解决你的问题,请参考以下文章

笔记:变量声明的提升

VsCode 代码片段-提升研发效率

[Effective JavaScript 笔记] 第12条:理解变量声明提升

es6学习笔记1

几条jQuery代码片段助力Web开发效率提升

基础笔记2(对象)