
在JavaScript中 let 和 const 主要以支持块级作用域而著称,但如果在代码块(如 {}、 if 、for 等语句的花括号)外部声明这些变量,会有以下情况:
1. 作用域范围
当在代码块外部声明 let 或 const 变量时,它们的作用域不再局限于某个块,而是取决于声明的位置:
在全局作用域(任何函数或代码块之外)声明 :变量将成为全局变量,但不会像 var那样挂载到全局对象(如浏览器中的 window 对象)上。这些变量在整个脚本文件中都可访问。
在函数内部但代码块外部声明 :变量的作用域将是整个函数,相当于函数作用域(类似 var ),但仍遵循 let 和 const 的其他特性(如无变量提升、存在暂时性死区等)。
2. 关键特性对比
无论在代码块内还是块外声明, let 和 const 始终保持以下核心特性:
无变量提升 :声明不会被提升到作用域顶部,访问未声明的变量会触ReferenceError 。
存在暂时性死区 :从作用域开始到变量声明前的区域,无法访问该变量。
不允许重复声明 :在同一作用域内,不能重复声明同名变量(无论之前是用 var 、let 还是 const 声明)。
不挂载到全局对象 :即使在全局作用域声明,也不会成为全局对象的属性。
3. 代码示例
示例1:全局作用域声明
// 全局作用域声明let和const
let globalLet = '全局let变量';
const globalConst = '全局const变量';
function test() {
console.log(globalLet); // 可访问,输出:全局let变量
console.log(globalConst); // 可访问,输出:全局const变量
}
test();
console.log(window.globalLet); // undefined(浏览器环境),let声明的全局变量不会挂载到window
console.log(window.globalConst); // undefined(浏览器环境),const同理示例2:函数内但代码块外声明
function demo() {
// 函数内、代码块外声明
let funcLet = '函数内的let变量';
const funcConst = '函数内的const变量';
if (true) {
// 块内可以访问函数作用域的变量
console.log(funcLet); // 输出:函数内的let变量
console.log(funcConst); // 输出:函数内的const变量
// 这里声明的变量是块级作用域
let blockLet = '块内let变量';
}
console.log(blockLet); // 报错:ReferenceError,无法访问块级作用域变量
}
demo();
console.log(funcLet); // 报错:ReferenceError,无法访问函数作用域变量示例3. let/const 不允许重复声明
// 代码块外(全局作用域)不允许重复声明
let globalVar = '第一次声明';
let globalVar = '第二次声明'; // 错误: Identifier 'globalVar' has already been declared
// 代码块内也不允许重复声明
if (true) {
let blockVar = '第一次声明';
let blockVar = '第二次声明'; // 错误: Identifier 'blockVar' has already been declared
}
// 即使跨作用域,全局声明和块内声明也不能重复
let globalVar = '全局声明';
if (true) {
let globalVar = '块内声明'; // 这里不是重复声明,而是创建了一个新的块级作用域变量,覆盖了全局变量
console.log(globalVar); // 输出: 块内声明
}
console.log(globalVar); // 输出: 全局声明4. 与 var 的对比
var :在代码块外声明是全局作用域,且 可以重复声明 ;在代码块内声明是函数作用域(非块级作用域),也 可以重复声明 。
let/const :无论在代码块内还是外声明,都 不可以重复声明 ;在代码块内声明是块级作用域,在代码块外是全局作用域
总结
代码块外声明的 let / const :作用域扩展到其声明所在的父级作用域(全局或函数作用域),但依然保持 let / const 的核心特性(无提升、有暂时性死区、不挂载全局对象等)。
代码块内声明的 let / const :作用域严格限制在当前代码块内,这是它们最常用的场景,用于创建局部变量以避免变量污染。
简单来说, let 和 const 的「块级作用域」特性体现在 它们可以被限制在代码块内 ,而不是说它们 必须 在代码块内声明。在块外声明时,它们的作用域会「扩大」到父级作用域,但依然保留其他重要特性。