JavaScript 声明提升 (Hoisting)
                           
天天向上
发布: 2025-02-26 23:20:13

原创
619 人浏览过

JavaScript 中的 声明提升 是指变量和函数的声明会被提升到当前执行环境的顶部。这意味着,在代码的执行过程中,变量和函数的声明会在代码执行前被处理,而不管它们在代码中的具体位置。

1. 变量声明提升 (var)

在使用 var 声明变量时,JavaScript 会将变量的声明(而不是赋值)提升到当前作用域的顶部。即使变量赋值语句在后面,变量仍然会在代码的最开始处被“声明”。

示例:使用 var 进行变量声明

console.log(x);  // 输出 undefined,因为 x 已被提升,但尚未赋值
var x = 5;
console.log(x);  // 输出 5

解释:

  1. 在代码执行前,var x; 会被提升到顶部,初始化为 undefined
  2. 然后,x = 5; 会在原位置执行,因此第一次 console.log(x) 输出的是 undefined,第二次输出的是 5

2. 函数声明提升

函数声明会被提升到顶部,意味着你可以在函数定义之前调用该函数。这适用于函数声明的情况,但不适用于函数表达式。

示例:函数声明提升

console.log(foo());  // 输出 "Hello!"

function foo() {
  return "Hello!";
}

解释:

  1. 在执行代码之前,整个函数声明(function foo() { ... })会被提升到顶部。
  2. 因此,即使 foo() 在调用时位于函数声明之前,代码仍然能够正常工作。

3. 函数表达式不会提升

如果将函数赋值给一个变量,那么该变量的声明会被提升,但是函数的定义不会被提升。因此,在调用之前引用该函数会导致 TypeError

示例:函数表达式不会提升

console.log(foo());  // TypeError: foo is not a function

var foo = function() {
  return "Hello!";
};

解释:

  1. var foo; 会被提升,但赋值 foo = function() {...} 会保持原来的位置。
  2. 由于函数表达式没有被提升,第一次调用 foo() 会导致 TypeError,因为在函数调用时,foo 的值为 undefined

4. let 和 const 的声明提升

letconst 也有类似的提升行为,但它们不会被初始化。它们会进入所谓的 “暂时性死区” (TDZ),即在声明之前访问它们会导致错误。

示例:let 和 const 的提升

console.log(a);  // ReferenceError: Cannot access 'a' before initialization
let a = 10;

解释:

  1. letconst 会被提升到顶部,但是它们不会初始化。在声明之前访问它们会抛出 ReferenceError
  2. 在上面的例子中,a 被提升,但在访问 a 之前,它还没有初始化,导致 ReferenceError

5. 总结:提升的行为

  • var 声明的变量会被提升到顶部,但初始化值不会被提升。变量的初始值是 undefined,直到执行到赋值语句。
  • 函数声明会被提升到顶部,意味着你可以在函数定义之前调用它。
  • 函数表达式的提升仅限于变量声明部分,函数本身不会被提升。
  • letconst 声明的变量会被提升到顶部,但进入暂时性死区,在声明之前无法访问。

6. 示例总结

// var 变量提升
console.log(a);  // undefined
var a = 2;

// 函数声明提升
console.log(foo());  // Hello!
function foo() {
  return "Hello!";
}

// 函数表达式不会提升
console.log(bar());  // TypeError: bar is not a function
var bar = function() {
  return "Hi!";
}

// let 和 const 提升到顶部,但有 TDZ
console.log(x);  // ReferenceError: Cannot access 'x' before initialization
let x = 10;

总结

  • 声明提升会将变量和函数的声明部分提升到当前作用域的顶部。
  • var 的变量会被提升,并初始化为 undefined
  • 函数声明会被完全提升(包括函数体)。
  • letconst 也会被提升,但在声明前访问它们会导致错误(ReferenceError)。
  • 函数表达式的赋值不会被提升,函数定义会在代码的实际位置执行。

更多详细信息请关注其他相关文章。

发表回复 0

Your email address will not be published. Required fields are marked *