es6中关于let的使用以及案例,包括但不限于块级作用域,不允许重复声明,没有变量提升,暂存性死区,不与顶层对象挂钩

ES6 let 关键字完整指南

1. 块级作用域

1.1 let vs var 作用域对比

js 复制代码
// var - 函数作用域
function varExample() {
  var x = 1;
  if (true) {
    var x = 2;  // 同一个 x
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

// let - 块级作用域
function letExample() {
  let x = 1;
  if (true) {
    let x = 2;  // 不同的 x
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

1.2 循环中的块级作用域

js 复制代码
// var 在循环中的问题
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);  // 3, 3, 3
}

// let 在循环中的正确行为
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);  // 0, 1, 2
}

2. 不允许重复声明

2.1 同一作用域重复声明

js 复制代码
// var 允许重复声明
var x = 1;
var x = 2;  // 正常工作

// let 不允许重复声明
let y = 1;
let y = 2;  // SyntaxError: Identifier 'y' has already been declared

// var 和 let 也不能重复声明
var z = 1;
let z = 2;  // SyntaxError: Identifier 'z' has already been declared

2.2 不同作用域的声明

js 复制代码
// 不同块级作用域可以声明同名变量
let x = 1;
if (true) {
  let x = 2;  // 正常工作
  console.log(x);  // 2
}
console.log(x);  // 1

3. 没有变量提升

3.1 var 的变量提升

js 复制代码
console.log(x);  // undefined
var x = 1;

// 等同于
var x;
console.log(x);
x = 1;

3.2 let 的非提升特性

js 复制代码
console.log(x);  // ReferenceError: Cannot access 'x' before initialization
let x = 1;

// 函数中也是一样
function example() {
  console.log(x);  // ReferenceError
  let x = 1;
}

4. 暂时性死区(TDZ)

4.1 基本概念

js 复制代码
// 在声明之前使用变量会导致 TDZ 错误
{
  console.log(x);  // ReferenceError
  let x = 1;
}

4.2 复杂场景中的 TDZ

js 复制代码
// 函数参数中的 TDZ
function example(x = y, y = 2) {
  return [x, y];
}
example();  // ReferenceError: y is not defined

// 条件语句中的 TDZ
if (true) {
  console.log(x);  // ReferenceError
  let x = 1;
}

5. 不与顶层对象挂钩

5.1 var 与顶层对象的关系

js 复制代码
// 浏览器环境
var x = 1;
console.log(window.x);  // 1

// Node.js 环境
var y = 1;
console.log(global.y);  // 1

5.2 let 与顶层对象的隔离

js 复制代码
// 浏览器环境
let x = 1;
console.log(window.x);  // undefined

// Node.js 环境
let y = 1;
console.log(global.y);  // undefined

6. 实际应用场景

6.1 循环中的闭包

js 复制代码
// 使用 var 的问题
const buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
  buttons[i].addEventListener('click', function() {
    console.log('Button ' + i + ' clicked');  // 总是显示最后一个 i
  });
}

// 使用 let 的解决方案
for (let i = 0; i < buttons.length; i++) {
  buttons[i].addEventListener('click', function() {
    console.log('Button ' + i + ' clicked');  // 正确显示当前按钮的索引
  });
}

6.2 模块封装

js 复制代码
// 使用 let 创建私有变量
{
  let privateData = 'secret';
  
  function doSomething() {
    console.log(privateData);
  }
  
  // 外部无法访问 privateData
  window.api = { doSomething };
}

7. 最佳实践

7.1 推荐用法

js 复制代码
// ✅ 使用 let 声明可变变量
let count = 0;
count++;

// ✅ 在循环中使用 let
for (let i = 0; i < array.length; i++) {
  // ...
}

// ✅ 在块级作用域中使用 let
if (condition) {
  let temp = calculate();
  // ...
}

7.2 避免的模式

js 复制代码
// ❌ 避免在声明前使用变量
function wrong() {
  console.log(x);  // 避免 TDZ 错误
  let x = 1;
}

// ❌ 避免重复声明
let x = 1;
let x = 2;  // 语法错误

// ❌ 避免与 var 混用
var y = 1;
let y = 2;  // 语法错误

8. 与 const 的对比

8.1 基本区别

js 复制代码
// let 允许重新赋值
let x = 1;
x = 2;  // 正常工作

// const 不允许重新赋值
const y = 1;
y = 2;  // TypeError: Assignment to constant variable

8.2 对象属性

js 复制代码
// let 和 const 都允许修改对象属性
let obj1 = { a: 1 };
obj1.a = 2;  // 正常工作

const obj2 = { a: 1 };
obj2.a = 2;  // 正常工作
obj2 = {};   // TypeError: Assignment to constant variable
相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄3 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端