let和var在全局上下文中存在五大差异:①作用域上var属函数级、let属块级;②提升上var声明与初始化均提升,let仅声明提升且存在TDZ;③全局对象绑定上var挂载window、let不挂载;④重复声明上var允许、let报错;⑤可见性上var可被函数内访问,let不可穿透。

在全局执行上下文中,let 和 var 的声明行为看似相似,实则存在关键差异:作用域边界、变量提升表现、以及是否挂载到全局对象上。
作用域范围不同
var 声明的变量属于全局作用域,但它的“可见范围”实际延伸至整个脚本(函数作用域层级),即使写在全局,也能被任意函数内访问(除非被同名局部变量遮蔽)。
let 声明的变量仅属于全局执行上下文的**块级作用域**——也就是最外层的 `{}` 级别(尽管全局代码没有显式大括号,ES规范仍将其视为一个块)。它不会被函数内部“穿透访问”,也不会污染全局对象属性。
变量提升与暂时性死区(TDZ)
var 声明会被完全提升:声明和初始化(赋值为 undefined)都提前到全局上下文顶部。因此,在声明前读取会得到 undefined,不报错。
let 声明也会被提升,但**不初始化**。从上下文开始到 let 语句执行前,该变量处于“暂时性死区”。此时访问会直接抛出 ReferenceError,无法绕过。
-
console.log(a); var a = 1;→ 输出undefined -
console.log(b); let b = 2;→ 报错:Cannot access 'b' before initialization
是否成为全局对象的属性
在浏览器环境中,全局 var 声明会自动作为 window 对象的可配置属性:
-
var x = 10;→window.x存在且值为10 -
delete window.x可成功删除(因为 var 声明的属性configurable: true)
let 声明**不会**绑定到 window(或 globalThis)上:
-
let y = 20;→window.y是undefined,不可访问 - 它只存在于全局环境记录(Global Environment Record)中,不暴露为全局对象属性
重复声明规则
var 允许在同一全局作用域中多次声明同名变量,后声明会覆盖前声明(无报错):
-
var z = 1; var z = 2;→ 合法,z 最终为 2
let 在全局作用域中不允许重复声明:
-
let w = 1; let w = 2;→ 报错:Identifier 'w' has already been declared - 即使中间有其他语句,只要在同一个全局块中,重复 let 就非法

















