You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何证明let与const声明存在变量提升现象?

Proving Variable Hoisting for let and const in JavaScript

Great question! This is one of JavaScript's trickiest nuances—those identical-looking ReferenceError messages sure do throw people off. Let's break down exactly how to prove that let and const do hoist, even though you can't access them before their declaration line.

First, Understand the Difference: Undeclared Variables vs. Temporal Dead Zone (TDZ)

When you access an undeclared variable like x, the JavaScript engine has no record of that variable existing at all—hence the Uncaught ReferenceError: x is not defined error.

For let/const variables, though, the engine does know the variable exists (thanks to hoisting) but locks it in the Temporal Dead Zone (TDZ) until the declaration line runs. The error message looks the same, but the underlying cause is totally different.


Test 1: Use typeof to Reveal the TDZ

The easiest way to spot the difference is with typeof:

  • For an undeclared variable, typeof returns "undefined" (no error, because the engine doesn't recognize the variable as existing).
  • For a let/const variable in the TDZ, typeof throws a ReferenceError (the engine knows the variable exists, but won't let you touch it yet).
// Undeclared variable: no hoisting, no TDZ
console.log(typeof x); // Outputs "undefined" — no error!

// let variable in TDZ: hoisted, but locked
console.log(typeof y); // Throws Uncaught ReferenceError: Cannot access 'y' before initialization
let y;

If y wasn't hoisted, typeof y would behave just like typeof x and return "undefined". The error here proves the engine is aware of y's existence—it just won't let you access it yet.

Test 2: Block Scope Shadowing

Another way to see hoisting in action is with block-level shadowing. If let didn't hoist, accessing a variable inside a block before its declaration would fall back to the outer scope's variable. But instead, it targets the hoisted (but locked) block-scoped variable:

let outerVar = 100;

{
  console.log(outerVar); // Throws ReferenceError: Cannot access 'outerVar' before initialization
  let outerVar = 200; // This declaration is hoisted to the top of the block
}

If hoisting didn't happen here, console.log(outerVar) would output 100 (the outer scope's value). Instead, it throws an error because the engine has already created the block-scoped outerVar binding (thanks to hoisting) and is blocking access until the declaration runs.

Test 3: Function Scope TDZ

Same logic applies to function scopes. A let variable inside a function is hoisted to the top of the function, but stays in the TDZ until its declaration:

function myFunc() {
  console.log(funcVar); // Throws ReferenceError: Cannot access 'funcVar' before initialization
  let funcVar = "hello";
}
myFunc();

If there was no hoisting, funcVar would be treated as a global variable (and throw a different error if it wasn't declared globally). The error here confirms the engine knows funcVar exists in the function scope—it's just locked in the TDZ.


Wrap-Up

To recap:

  • let and const do hoist—their bindings are created when the scope is entered (function or block).
  • The catch is they're immediately locked in the TDZ, so you can't access them until the declaration statement executes.
  • The identical error messages are a red herring—use typeof tests and scope shadowing to prove the hoisting is happening under the hood.

内容的提问来源于stack exchange,提问作者Shammi Hans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 18:19:05