blogSite

我是谁?我在哪儿?我在干什么?

View project on GitHub

JavaScript 提升(Hoisting)

  • 提升(Hoisting)是 JavaScript 将声明移至顶部的默认行为。

JavaScript 声明会被提升

例子 1例子 2 的结果相同:

  • 例子 1
  x = 5; // 把 5 赋值给 x
  
  elem = document.getElementById("demo"); // 查找元素
  elem.innerHTML = x;                     // 在元素中显示 x

  var x; // 声明 x
  • 例子 2
  var x; // 声明 x
  x = 5; // 把 5 赋值给 x

  elem = document.getElementById("demo"); // 查找元素
  elem.innerHTML = x;                     // 在元素中显示 x

为了理解这一点,您必须理解术语 “hoisting”。 Hoisting 是 JavaScript 将所有声明提升到当前作用域顶部的默认行为(提升到当前脚本或当前函数的顶部)。

let 和 const 关键字

letconst 声明的变量和常量不会被提升!

  • let关键字
    • 中重新声明变量不会重新声明块外的变量
      var x = 10;
      // 此处 x 为 10
      { 
        let x = 6;
        // 此处 x 为 6
      }
      // 此处 x 为 10
    
    • 循环作用域
      var i = 7;
      for (var i = 0; i < 10; i++) {
        // 一些语句
      }
      // 此处,i 为 10
    
    
      let i = 7;
      for (let i = 0; i < 10; i++) {
        // 一些语句
      }
      // 此处 i 为 7
    

    在第一个例子中,在循环中使用的变量使用 var 重新声明了循环之外的变量。 在第二个例子中,在循环中使用的变量使用 let 并没有重新声明循环外的变量。 如果在循环中用 let 声明了变量 i,那么只有在循环内,变量 i 才是可见的。

    • 函数作用域 在函数内声明变量时,使用 varlet 很相似。
      function myFunction() {
        var carName = "porsche";   // 函数作用域
      }
      function myFunction() {
        let carName = "porsche";   // 函数作用域
      }
      
    • 全局作用域 如果在块外声明声明,那么 varlet 也很相似。
      var x = 10;       // 全局作用域
      let y = 6;       // 全局作用域
      

      使用 JavaScript 的情况下,全局作用域是 JavaScript 环境。 在 HTML 中,全局作用域是 window 对象。

      // 通过 `var` 关键词定义的全局变量属于 window 对象:
      var carName = "porsche";
      // 此处的代码可使用 window.carName
      
      // 通过 let 关键词定义的全局变量不属于 window 对象:
      let carName = "porsche";
      // 此处的代码不可使用 window.carName
      
  • const关键字
    • 通过 const 定义的变量与 let 变量类似,但不能重新赋值:
      const PI = 3.141592653589793;
      PI = 3.14;      // 会出错
      PI = PI + 10;   // 也会出错
    
  • JavaScript const 变量必须在声明时赋值:
  // 不正确
  const PI;
  PI = 3.14159265359;

  // 正确
  const PI = 3.14159265359;
  • 可以修改数组对象内的内容,不能修改数组、对象本身

    JavaScript 初始化不会被提升

    JavaScript 只提升声明,而非初始化。 例子 1例子 2 的结果不相同:

  • 例子 1
  var x = 5; // 初始化 x
  var y = 7; // 初始化 y

  elem = document.getElementById("demo"); // 查找元素
  elem.innerHTML = x + " " + y;           // 显示 x 和 y

  // 结果:5 7
  • 例子 2
  var x = 5; // 初始化 x
  
  elem = document.getElementById("demo"); // 查找元素
  elem.innerHTML = x + " " + y;           // 显示 x 和 y
  
  var y = 7; // 初始化 y 

  // 结果:x is 5 and y is undefined

最后一个例子中的 y 仍然是未定义能说得通吗? 这是因为只有声明(var y)而不是初始化(=7)被提升到顶部。 由于 hoisting,y 在其被使用前已经被声明,但是由于未对初始化进行提升,y 的值仍是未定义。

在顶部声明您的变量!

Hoisting(对很多开发者来说)是 JavaScript 的一种未知的或被忽视的行为。 如果开发者不理解 hoisting,程序也许会包含 bug(错误)。 为了避免 bug,请始终在每个作用域的开头声明所有变量。 由于这就是 JavaScript 解释代码的方式,请保持这个好习惯。 严格模式("use strict")中的 JavaScript 不允许在未被声明的情况下使用变量。 警告 "use strict"; 定义 JavaScript 代码应该以“严格模式”执行。 "use strict" 指令只能在脚本或函数的开头被识别。

参考内容

首页 > 学习总览 > 开发语言 > JavaScript