Javascript's Hoisting(变量提升、函数提升、类提升)

Function hoisting

const callerArrow = () => {
    return callee(); // 刚定义这个函数时,callee 的状态是:defined but uninitialized
                     // 只要 callee 在调用这个函数之前初始化了就没有问题
};

// callee(); // 见不到定义,调用会出错

const callee = () => {
    console.log("Hello from callee!")
};

callerArrow(); // callee 的定义出现了,可以调用

calleeRegular();
function calleeRegular() {
    console.log("Hello from calleeRegular!")
}

在同一个词法定义域中的所有声明都是能被看见的。但如果声明是函数,则还能支持直接(向后)调用,即函数提升规则。如果是箭头函数,则只能引用,不能调用。

为什么箭头函数和普通函数有这样的区别?因为箭头函数没有用到 function 关键字,是按照变量的方式来定义的,遵循的是变量提升规则。

Variable hoisting

console.log(a)
a = 1

尝试修改第二行:

定义方式作用域hoisting?程序执行结果
a = 1全局ReferenceError: a is not defined
var a = 1局部打印 undefined(因为 var 变量有默认值)
let = 1局部ReferenceError: Cannot access 'a' before initialization
const = 1局部ReferenceError: Cannot access 'a' before initialization

Class hoisting

const Dog = new Animal("Bingo")
// ReferenceError: Cannot access 'Animal' before initialization

class Animal {
  constructor(name) {
    this.name = name
  }
}

和用 const 定义的变量的提升规则一样。

总结

提升能工作是因为解释器能看到对应的声明。如果是普通函数,能直接调用;如果是 var 声明的变量,在初始化时使用默认值 undefined