在JavaScript中 let 变量的重复声明规则非常严格,默认情况下不允许重复声明 。但存在一种特殊情况:在 不同的作用域 中可以声明同名的 let 变量(这属于变量遮蔽现象)。下面详细解释:

一、let的核心规则:同一作用域内禁止重复声明

根据ES6规范 let 声明的变量具有「 不允许同一作用域内重复声明 」的特性。具体表现为:

  • 同一代码块内 :不能用 let 重复声明已存在的变量(无论之前是用 let 、 var还是 const 声明的)。

  • 函数作用域内 :不能用 let 重复声明函数作用域内已存在的变量。

违反此规则会直接抛 SyntaxError 错误 (语法错误,在代码解析阶段就会报错,不会执行)。

示例1:同一代码块内重复声明

{  
  let a = 10;  
  let a = 20; // 语法错误:SyntaxError: Identifier 'a' has already been declared  
}

示例2:与var/const在同一作用域重复声明

{  
  var b = 10;  
  let b = 20; // 语法错误:SyntaxError: Identifier 'b' has already been declared  
}

{  
  const c = 10;  
  let c = 20; // 语法错误:SyntaxError: Identifier 'c' has already been declared  
}

二、let允许「重复声明」的唯一情况:不同作用域的变量遮蔽

let 变量 只有在不同作用域中 才可以声明同名变量,这种情况被称为「 变量遮蔽 」(Variable Shadowing)。此时,内层作用域的变量会「遮蔽」外层作用域的同名变量,但它们本质上是两个独立的变量。

示例3:不同作用域的同名let变量

// 外层作用域声明let变量
let x = 100;

function test() {
  // 内层作用域可以声明同名的let变量(这不是重复声明,而是创建了新变量)
  let x = 200;
  console.log(x); // 输出:200(访问的是内层变量)
}

test();
console.log(x); // 输出:100(访问的是外层变量)

示例4:代码块内的变量遮蔽

let y = 300;

if (true) {
  let y = 400; // 内层块级作用域的y,遮蔽外层的y
  console.log(y); // 输出:400
}

console.log(y); // 输出:300(外层的y不受影响)

三、注意事项

  • 变量遮蔽≠重复声明 :变量遮蔽是在不同作用域中创建同名变量,而重复声明是在同一作用域中声明已存在的变量。

  • 严格模式与非严格模式 : let 的重复声明规则在严格模式和非严格模式下都适用(因let本身是ES6的严格特性)。

  • 全局作用域的特殊情况 :即使在全局作用域用 let 声明的变量,也不会挂载到全局对象(如 window )上,因此不会与全局对象的属性产生冲突,但仍遵循同一作用域不重复声明的规则。

总结

let 变量 只有在不同作用域中 可以声明同名变量(变量遮蔽),而在 同一作用域内永远不允许重复声明 (会直接抛出语法错误)。这一特性是 let 相比 var 更严格的表现之一,旨在避免变量重复声明导致的逻辑混乱和潜在错误。