JavaScript教程 / 全部 / 前端 / 技术 · 2022年4月29日 0

13 – JavaScript 中的提升

原文地址:https://dev.to/bhagatparwinder/hoisting-in-javascript-2aj2

什么是提示?

JavaScript 中的提升允许你在变量和函数声明之前使用它们。

函数提升

console.log(helloWorld()); // Hello World
console.log(multiplyNumbers(10, 5)); // 50

function helloWorld() {
    return "Hello World";
}

function multiplyNumbers(a, b) {
    return a * b;
}

如你所见,我在两个函数声明之前使用了它们并且 JavaScript 没有报错。打印出了预期的结果。使用函数之前先声明是一个好习惯。

var 声明变量提升

console.log(age); // undefined
console.log(foo); // Reference Error: foo is not defined

var age = 10;

我可以在变量声明之前使用它。打印出了 undefined,但并没有抛出错误。和打印 foo 相比,你会看到那条语句抛出了一个错误。

let 和 const 声明变量提示

let 和 const 声明的变量也会提升,但并不像 var 声明的那样默认初始化一个默认值 undefined。在初始化之前读取通过 let 或 const 声明的变量则会抛出错误。

console.log(num); // Throws ReferenceError exception as the variable value is uninitialized
let num = 6; // Initialization

注意,代码的执行顺序起关键作用而不是代码在文件中的书写顺序。在任何读取它的代码之前初始化就不会有报错。

这里加一些 TDZ(Temporal dead zone)的内容,TDZ 是指从块级作用域的开始到变量声明结束:

{ // TDZ starts at beginning of scope
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2; // End of TDZ (for foo)
}

之所以称为“暂时”,那是因为区域是根据代码的执行顺序(时间)而不是代码的书写顺序(位置)。例如:下面例子可以正常工作,即使函数在 let 声明的变量之前使用它,这个函数已经出了 TDZ 的范围。

{
    // TDZ starts at beginning of scope
    const func = () => console.log(letVar); // OK

    // Within the TDZ letVar access throws `ReferenceError`

    let letVar = 3; // End of TDZ (for letVar)
    func(); // Called outside TDZ!
}

提升的警告

为什么没有打印 age 的值呢?

JavaScript 只提升声明,并不提升初始化。

就像例子中的 age ,只提升了声明并没有把值赋值给它。由于只提升了声明这个原则,若例子中是函数表达式你则无法使用提升来使用它。

console.log(helloWorld()); // helloWorld is not defined
console.log(multiplyNumbers(10, 5));

const helloWorld = function () {
    return "Hello World";
}

const multiplyNumbers = function (a, b) {
    return a * b;
}

更多参考 MDN