ES6 let 和 const

一、基本概念与声明方式

1. let 声明

let 允许你声明一个块级作用域的局部变量,可以选择性地将其初始化为一个值。

javascript 复制代码
let x = 1;
if (true) {
  let x = 2;  // 不同的变量
  console.log(x);  // 2
}
console.log(x);  // 1

2. const 声明

const 声明创建一个块级作用域的常量,其值不能被重新赋值。

javascript 复制代码
const PI = 3.14159;
// PI = 3.14;  // TypeError: Assignment to constant variable

const obj = { name: 'John' };
obj.name = 'Jane';  // 合法,修改对象属性
// obj = {};  // 非法,不能重新赋值

二、关键特性详解

1. 块级作用域 (Block Scope)

let 和 const 引入了真正的块级作用域,不同于 var 的函数作用域。

javascript 复制代码
{
  let blockScoped = 'visible inside block';
  const alsoBlockScoped = 'same here';
}
console.log(blockScoped);  // ReferenceError
console.log(alsoBlockScoped);  // ReferenceError

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);  // 0, 1, 2
}

2. 暂时性死区 (Temporal Dead Zone, TDZ)

在声明前访问 let 或 const 变量会导致 ReferenceError,从进入作用域到声明完成之间的区域称为TDZ。

javascript 复制代码
console.log(aLetVar);  // ReferenceError
let aLetVar = 10;

// 对比var
console.log(aVar);  // undefined
var aVar = 10;

3. 无作用域提升 (No Hoisting)

虽然 let 和 const 声明在编译阶段被处理(类似"提升"),但在声明前不可访问。

javascript 复制代码
function test() {
  console.log(hoistedVar);  // undefined
  console.log(notHoistedLet);  // ReferenceError
  
  var hoistedVar = 1;
  let notHoistedLet = 2;
}

4. 禁止重复声明

在同一作用域内,let 和 const 不允许重复声明变量。

javascript 复制代码
let x = 1;
let x = 2;  // SyntaxError: Identifier 'x' has already been declared

var y = 1;
let y = 2;  // 同样报错

三、与 var 的详细对比

特性 var let const
作用域 函数作用域 块级作用域 块级作用域
提升 声明提升,初始化为undefined 存在TDZ,不可提前访问 存在TDZ,不可提前访问
全局声明时成为window属性 是 否 否
重复声明 允许 不允许 不允许
值可变性 可变 可变 不可重新赋值(对象内容可修改)

四、词法作用域 (Lexical Scope)

let 和 const 遵循词法作用域规则,作用域在代码编写时就已经确定。

javascript 复制代码
function outer() {
  let outerVar = 'outer';
  
  function inner() {
    console.log(outerVar);  // 可以访问外部变量
    let innerVar = 'inner';
  }
  
  inner();
  // console.log(innerVar);  // ReferenceError
}
outer();

五、实际应用场景

1. 循环中的变量绑定

javascript 复制代码
// var 的问题
for (var i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 0);  // 5,5,5,5,5
}

// let 的解决方案
for (let j = 0; j < 5; j++) {
  setTimeout(() => console.log(j), 0);  // 0,1,2,3,4
}

2. 常量声明

javascript 复制代码
// 配置常量
const API_ENDPOINT = 'https://api.example.com';
const MAX_RETRIES = 3;
const DEFAULT_TIMEOUT = 5000;

// 对象常量(内容可修改)
const USER_ROLES = {
  ADMIN: 'admin',
  USER: 'user',
  GUEST: 'guest'
};

3. 块级作用域实用案例

javascript 复制代码
// 条件性变量声明
if (userLoggedIn) {
  let authToken = getToken();
  // 仅在此块中使用token
}

// switch语句中的块作用域
switch (condition) {
  case 1: {
    let message = 'Case 1';
    console.log(message);
    break;
  }
  case 2: {
    let message = 'Case 2';  // 不冲突
    console.log(message);
    break;
  }
}

六、常见误区与最佳实践

1. const 并不意味着不可变

javascript 复制代码
const arr = [1, 2, 3];
arr.push(4);  // 合法
// arr = [1,2,3,4];  // 非法

const obj = { name: 'John' };
obj.name = 'Jane';  // 合法

如果需要完全不可变的对象,可以使用 Object.freeze():

javascript 复制代码
const frozenObj = Object.freeze({ name: 'John' });
frozenObj.name = 'Jane';  // 静默失败(严格模式下报错)

2. 优先使用 const,其次是 let

现代 JavaScript 开发推荐:

  1. 默认使用 const
  2. 只有当变量需要重新赋值时才使用 let
  3. 避免使用 var

3. 全局声明的影响

javascript 复制代码
var globalVar = 1;
let globalLet = 2;

console.log(window.globalVar);  // 1
console.log(window.globalLet);  // undefined

七、底层原理

1. 变量创建的三阶段

  1. 声明阶段:在作用域中注册变量
  2. 初始化阶段:分配内存并绑定作用域(TDZ结束)
  3. 赋值阶段:给变量赋值

var 在声明阶段即初始化(为undefined),而 let/const 将初始化和赋值分开。

2. 执行上下文的变化

javascript 复制代码
{
  // let x 的声明被"提升"但未初始化
  console.log(x);  // ReferenceError
  let x = 10;
  // 初始化完成
}

八、迁移建议

从 var 迁移到 let/const 时:

  1. 将函数内所有 var 改为 const
  2. 将需要重新赋值的变量改为 let
  3. 注意检查循环和闭包中的变量引用
  4. 使用 linter 工具帮助检测 var 的使用
javascript 复制代码
// 迁移前
function oldWay() {
  var a = 1;
  var b = 2;
  for (var i = 0; i < 10; i++) {
    // ...
  }
}

// 迁移后
function newWay() {
  const a = 1;
  let b = 2;
  for (let i = 0; i < 10; i++) {
    // ...
  }
}
相关推荐
const_qiu18 分钟前
第一章 1.1-1.2:基础模型调用与 TypeScript 入门 —— Java 开发者的视角
java·javascript·typescript
风骏时光牛马19 分钟前
用户管理模块接口开发
前端
彭亚川Allen41 分钟前
从零手搓 RAG 之检索全流程,给大模型接上自己的知识库
前端·后端·ai编程
IT_陈寒43 分钟前
别让Java字符串拼接偷偷吃掉你的内存
前端·人工智能·后端
软件技术NINI1 小时前
圣罗兰彩妆html+css 4页
前端·css·html
2601_951615202 小时前
网站模板 网站网页模板下载
前端·网络·html
酷炫码神2 小时前
Day 1|HTML5:一个商城首页的骨架,从 DOCTYPE 到语义化
前端·html·html5
AI源码3 小时前
鲜花商城(HTML 版)
前端·html
hiahiahia1233 小时前
Message 和对话
服务器·前端·数据库
溪语流沙3 小时前
【Web全栈进阶】Composition API与组件通信:props深入、emit、插槽
前端·css·vue.js