1.1 let 和 const

letconst 是 ES6 新增的变量声明方式,用来替代老式的 var

var 有很多"坑"——变量提升、全局污染、重复声明不报错……letconst 修复了这些问题。

let vs const vs var 对比:
特性 var let const
重复声明 ✅ 可以 ❌ 报错 ❌ 报错
重新赋值 ✅ 可以 ✅ 可以 ❌ 报错
作用域 函数级 块级 块级
变量提升 ✅ 会提升(值为 undefined) ❌ 暂时性死区 ❌ 暂时性死区
💡 块级作用域:简单说就是大括号 {} 里面就是一个作用域,let/const 声明的变量只在这个 {} 里面有效。
1// ========== let ========== 2let name = '小明'; 3console.log(name); // 小明 4 5// let 可以重新赋值 6name = '小红'; 7console.log(name); // 小红 8 9// let 不能重复声明 10// let name = '小刚'; // ❌ 报错:Identifier 'name' has already been declared 11 12// let 的块级作用域 13if (true) { 14 let age = 18; 15 console.log(age); // 18(在 if 大括号里面,能访问) 16} 17// console.log(age); // ❌ 报错:age is not defined 18 19// ========== const ========== 20const PI = 3.14159; 21console.log(PI); // 3.14159 22 23// const 不能重新赋值 24// PI = 3.14; // ❌ 报错:Assignment to constant variable 25 26// const 必须在声明时赋值 27// const GRAVITY; // ❌ 报错:Missing initializer in const declaration 28 29// 特别注意:const 对象/数组可以修改内容 30const person = { name: '张三' }; 31person.name = '李四'; // ✅ 这不报错! 32console.log(person.name); // 李四 33// person = { name: '王五' }; // ❌ 这才报错
代码逐行讲解:
代码 说明
let name = '小明' let 声明变量,可重新赋值
name = '小红' 重新赋值,合法
let age = 18(在 if 里) age 只在 {} 块内有效
const PI = 3.14159 const 声明常量,不能重新赋值
person.name = '李四' const 对象可以修改属性,但不能重新赋值整个变量
使用建议:
场景 用什么 原因
值不会变 const 安全,防止误改
值会变 let var 安全,块级作用域
别用 var let + const 足够,var 容易出 bug
⚠️ 新手易错const 声明的对象可以修改属性。const 保证的是变量指向的地址不变,不是内容不变。person.name = '李四' 变的是对象里面的属性,对象本身的地址没变,所以不报错。
⚠️ 新手易错:在 for 循环里用 var 声明的 i,循环结束后还能访问;换成 let 就不行了,因为 let 的作用域被限制在 for{} 里面。

1.2 模板字符串

模板字符串用反引号 ` 包裹字符串,可以用 ${变量} 直接插入变量,不用手动拼接。

以前拼字符串要用 '你好,' + name + '!',有了模板字符串直接写 `你好,${name}!` 就行。

基本语法`字符串内容 ${变量或表达式}`
1let name = '小明'; 2let age = 18; 3 4// 传统方式拼接字符串 5let old = '我叫' + name + ',今年' + age + '岁'; 6console.log(old); // 我叫小明,今年18岁 7 8// 模板字符串(更清晰) 9let str = `我叫${name},今年${age}岁`; 10console.log(str); // 我叫小明,今年18岁 11 12// 可以在 ${} 里写表达式 13let price = 9.9; 14let quantity = 3; 15console.log(`总价:${price * quantity}元`); // 总价:29.7元 16 17// 模板字符串支持换行 18let html = ` 19 <div> 20 <h2>${name}</h2> 21 <p>年龄:${age}</p> 22 </div> 23`; 24console.log(html);
代码逐行讲解:
代码 说明
`我叫${name},今年${age}岁` 反引号 + ${变量名},直接插入变量
`总价:${price * quantity}元` ${} 里可以写任意表达式
反引号内的换行 反引号天然支持多行,不会报错
普通字符串 vs 模板字符串:
特性 普通字符串 ' ' / " " 模板字符串 ` `
插变量 要用 + 拼接 直接 ${变量}
多行 不支持(要加 \n 支持(直接回车换行)
引号嵌套 容易混淆 内部可以用 '"
⚠️ 新手易错:模板字符串用的是反引号 `(键盘左上角,数字1左边),不是单引号 '。写错引号会报错或得到错误的结果。
⚠️ 新手易错:变量要用 ${} 包裹,不能直接写变量名。`你好,name` 输出的是字面量 你好,name,不是变量的值。

1.3 解构赋值

解构赋值就是从数组或对象里快速取出值,赋给变量。不用一个一个手动取。

1.3.1 数组解构

位置(下标顺序)提取值。

let [变量1, 变量2, ...] = 数组;

1// 传统方式取数组值 2let colors = ['红色', '绿色', '蓝色']; 3let c1 = colors[0]; 4let c2 = colors[1]; 5let c3 = colors[2]; 6 7// 解构赋值(一步搞定) 8let [red, green, blue] = colors; 9console.log(red); // 红色 10console.log(green); // 绿色 11console.log(blue); // 蓝色 12 13// 跳过某些值 14let [first, , third] = ['A', 'B', 'C']; 15console.log(first); // A 16console.log(third); // C(中间的 B 被跳过了) 17 18// 默认值 19let [a, b = '默认值'] = ['hello']; 20console.log(a); // hello 21console.log(b); // 默认值(数组里没有第2个值,所以用默认值)

1.3.2 对象解构

属性名提取值(最常用)。

let { 属性名1, 属性名2, ... } = 对象;

1// 传统方式取对象属性 2let person = { name: '张三', age: 25, city: '北京' }; 3let name1 = person.name; 4let age1 = person.age; 5 6// 解构赋值(一步搞定) 7let { name, age, city } = person; 8console.log(name); // 张三 9console.log(age); // 25 10console.log(city); // 北京 11 12// 变量重命名 13let { name: personName, age: personAge } = person; 14console.log(personName); // 张三 15console.log(personAge); // 25 16 17// 默认值 18let { hobby = '未设置' } = person; 19console.log(hobby); // 未设置 20 21// 函数参数解构 22function greet({ name, age }) { 23 console.log(`你好,我叫${name},${age}岁`); 24} 25greet(person); // 你好,我叫张三,25岁
代码逐行讲解:
代码 说明
let { name, age } = person 从对象 person 中取出 nameage 属性
let { name: personName } = person 取出 name 属性,但变量名叫 personName
let { hobby = '未设置' } = person person 没有 hobby,所以用默认值
function greet({ name, age }) 函数参数直接解构,调用时传对象即可
⚠️ 新手易错:对象解构的变量名必须和属性名一致let { username } = person 拿到的是 undefined,因为对象里没有 username 这个属性。要用别名的话写 let { name: username } = person

1.4 展开运算符与剩余参数

展开运算符 ... 用三个点表示,功能是把数组或对象"展开",剩余参数则用来收集多个值

1.4.1 展开运算符(Spread)

把数组/对象的元素"拆开"。

1// ========== 数组展开 ========== 2let arr1 = [1, 2, 3]; 3let arr2 = [4, 5, 6]; 4 5// 合并数组 6let merged = [...arr1, ...arr2]; 7console.log(merged); // [1, 2, 3, 4, 5, 6] 8 9// 数组复制(浅拷贝) 10let arrCopy = [...arr1]; 11console.log(arrCopy); // [1, 2, 3] 12 13// 在数组中间插入元素 14let arr = [1, 2, 5]; 15let newArr2 = [...arr.slice(0, 2), 3, 4, ...arr.slice(2)]; 16console.log(newArr2); // [1, 2, 3, 4, 5] 17 18// ========== 对象展开 ========== 19let baseInfo = { name: '张三', age: 25 }; 20let extraInfo = { city: '北京', job: '程序员' }; 21 22// 合并对象 23let fullInfo = { ...baseInfo, ...extraInfo }; 24console.log(fullInfo); 25// { name: '张三', age: 25, city: '北京', job: '程序员' } 26 27// 对象复制(浅拷贝)+ 修改 28let updated = { ...baseInfo, age: 26, city: '上海' }; 29console.log(updated); 30// { name: '张三', age: 26, city: '上海' }

1.4.2 剩余参数(Rest)

和展开相反——把多个参数收集到一个数组里

1// 剩余参数收集多个值 2function sum(...numbers) { 3 let total = 0; 4 for (let i = 0; i < numbers.length; i++) { 5 total += numbers[i]; 6 } 7 return total; 8} 9 10console.log(sum(1, 2, 3)); // 6 11console.log(sum(10, 20, 30, 40)); // 100 12 13// 第一个参数单独取,剩下的收集起来 14function introduce(first, ...others) { 15 console.log('第一个:' + first); 16 console.log('其余的:' + others.join('、')); 17} 18 19introduce('苹果', '香蕉', '橘子', '西瓜'); 20// 第一个:苹果 21// 其余的:香蕉、橘子、西瓜 22 23// 对象解构 + 剩余参数 24let { name, ...rest } = { name: '张三', age: 25, city: '北京' }; 25console.log(name); // 张三 26console.log(rest); // { age: 25, city: '北京' }
展开 vs 剩余对比:
特性 展开(Spread) 剩余(Rest)
符号 ... ...
位置 右边(把东西拆开) 左边(把东西收集起来)
场景 合并/复制数组和对象 函数参数收集
⚠️ 新手易错:展开运算符是浅拷贝。如果数组或对象里有嵌套的引用类型(比如数组里的数组),复制的只是引用地址,不是真正的副本。修改嵌套内容会影响到原数组/对象。
⚠️ 新手易错:对象展开时,后面的同名属性会覆盖前面的。{ name: 'A', ...{ name: 'B' } } 结果是 { name: 'B' }

1.5 对象简写

对象简写是 ES6 提供的语法糖,让你写对象时少敲几个字。

属性简写:当变量名和属性名相同时,可以省略冒号和值。

方法简写:定义方法时可以省略 function 关键字。

1let name = '张三'; 2let age = 25; 3 4// ========== 属性简写 ========== 5// ES5 写法 6let personOld = { 7 name: name, 8 age: age, 9 city: '北京' 10}; 11 12// ES6 简写(属性名和变量名相同时省略) 13let personNew = { 14 name, // 等价于 name: name 15 age, // 等价于 age: age 16 city: '北京' // 变量名不同,不能简写 17}; 18 19console.log(personNew); // { name: '张三', age: 25, city: '北京' } 20 21// ========== 方法简写 ========== 22// ES5 写法 23let calculatorOld = { 24 add: function(a, b) { 25 return a + b; 26 }, 27 subtract: function(a, b) { 28 return a - b; 29 } 30}; 31 32// ES6 简写 33let calculatorNew = { 34 add(a, b) { // 等价于 add: function(a, b) {...} 35 return a + b; 36 }, 37 subtract(a, b) { 38 return a - b; 39 } 40}; 41 42console.log(calculatorNew.add(10, 5)); // 15 43console.log(calculatorNew.subtract(10, 5)); // 5 44 45// ========== 配合解构和展开一起用 ========== 46let title = 'ES6 真好用'; 47let content = '学习ES6让代码更简洁'; 48 49// 展开 + 简写 50let article = { title, content, ...{ date: '2026-06-12', views: 100 } }; 51console.log(article); 52// { title: 'ES6 真好用', content: '学习ES6让代码更简洁', date: '2026-06-12', views: 100 }
代码逐行讲解:
代码 说明
{ name, age } 属性名和变量名相同,省略 name: name
{ add(a, b) {} } 方法定义省略 function
{ ...{ date, views } } 配合展开运算符合并对象
简写前后对比:
特性 ES5 写法 ES6 简写
属性 { name: name } { name }
方法 { add: function() {} } { add() {} }
⚠️ 新手易错:属性简写只在变量名和属性名完全相同时才能用。如果变量叫 userName 但属性想叫 name,必须写 { name: userName },不能简写。

实践作业

题目:用解构和展开运算符重构用户信息对象。

要求

  1. 定义一个基础用户对象 baseUser,包含 nameagecity
  2. 定义一个扩展信息对象 extraInfo,包含 jobhobby
  3. 用展开运算符合并两个对象为 fullUser
  4. 用解构赋值从 fullUser 中提取 namejob
  5. 用模板字符串打印:"我是[名字],职业是[职业]"
  6. 创建一个新对象 student,使用属性简写和展开运算符,添加 school 属性
💡 参考答案(先自己写,再对照):
1// 1. 基础用户对象 2let baseUser = { name: '张三', age: 25, city: '北京' }; 3 4// 2. 扩展信息对象 5let extraInfo = { job: '前端开发', hobby: '写代码' }; 6 7// 3. 合并对象 8let fullUser = { ...baseUser, ...extraInfo }; 9console.log(fullUser); 10// { name: '张三', age: 25, city: '北京', job: '前端开发', hobby: '写代码' } 11 12// 4. 解构提取 13let { name, job } = fullUser; 14 15// 5. 模板字符串打印 16console.log(`我是${name},职业是${job}`); 17// 我是张三,职业是前端开发 18 19// 6. 创建 student 对象 20let school = '清华大学'; 21let student = { ...fullUser, school, grade: '大三' }; 22console.log(student); 23// { name: '张三', age: 25, city: '北京', job: '前端开发', hobby: '写代码', school: '清华大学', grade: '大三' }

本章复盘——ES6 核心特性要点

特性 一句话说明
let / const const 用来声明不会重新赋值的变量,let 用来声明会变的变量,var 不再使用
模板字符串 反引号 ` + ${变量},支持多行和嵌入表达式
数组解构 let [a, b] = [1, 2],按位置取值
对象解构 let { name, age } = obj,按属性名取值
展开运算符 ... 把数组/对象拆开,用于合并和复制
剩余参数 function fn(...args) 把多个参数收集为数组
对象简写 属性名 = 变量名时省略冒号值;方法省略 function