2. JavaScript ES6+ 核心语法:let/const、箭头函数、模板字符串、解构赋值、展开运算符、模块化(import/export)
好,咱们进入第二章。ES6+ 的语法,说白了就是现代 JavaScript 的基石。你想想看,现在哪个前端项目不用这些?我当年刚入行时还在写 var 和拼接字符串,那叫一个痛苦。后来 ES6 一出来,整个编码体验直接起飞。
这一章我会带你逐个击破。每个知识点我都会结合实战经验来讲,保证你学完就能用。
2.1 let 与 const:告别 var 的混乱时代
先说说 let 和 const。它们解决了 var 的两个大问题:作用域混乱和变量提升带来的坑。
let:块级作用域
let 只在它所在的 {} 内有效。我见过不少新手用 var 在 for 循环里定义变量,结果循环结束后变量还活着,导致各种诡异 bug。
// 错误示范(用 var)
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 输出:3, 3, 3(因为 var 没有块级作用域)
// 正确示范(用 let)
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 输出:0, 1, 2
const:常量声明
const 声明一个只读的常量。注意,它保证的是引用地址不变,而不是值不可变。举个例子:
const person = { name: '张三' };
person.name = '李四'; // 可以修改属性
// person = { name: '王五' }; // 报错!不能重新赋值
arr = [] 清空数组,结果报错了。记住:const 管的是「不能重新指向」,不是「不能修改内容」。
2.2 箭头函数:更简洁的 this 绑定
箭头函数有两个核心特点:语法简洁,以及不绑定自己的 this。
基本语法
// 传统函数
function add(a, b) {
return a + b;
}
// 箭头函数
const add = (a, b) => a + b;
// 如果只有一个参数,可以省略括号
const double = x => x * 2;
// 如果没有参数,必须写空括号
const sayHello = () => console.log('Hello');
this 指向问题
箭头函数没有自己的 this,它会捕获外层作用域的 this。这一点在 React 组件中特别有用。
// 传统函数的问题
const obj = {
name: 'obj',
logName: function() {
setTimeout(function() {
console.log(this.name); // undefined(this 指向 window)
}, 100);
}
};
// 箭头函数的解决方案
const obj2 = {
name: 'obj2',
logName: function() {
setTimeout(() => {
console.log(this.name); // 'obj2'(this 指向 obj2)
}, 100);
}
};
实战经验:我在写 React 类组件时,经常用箭头函数来避免手动绑定 this。比如 handleClick = () => { ... },这样就不用在 constructor 里写 this.handleClick = this.handleClick.bind(this) 了。
arguments 对象。如果你需要这些特性,还是用传统函数吧。
2.3 模板字符串:告别字符串拼接
模板字符串用反引号(`)包裹,支持嵌入变量和表达式。我个人觉得这是 ES6 最实用的特性之一。
const name = '张三';
const age = 25;
// 传统拼接
const msg1 = '我叫' + name + ',今年' + age + '岁。';
// 模板字符串
const msg2 = `我叫${name},今年${age}岁。`;
多行字符串
以前写多行字符串得用 \n 或者数组 join,现在直接写:
const html = `
<div>
<h1>标题</h1>
<p>内容</p>
</div>
`;
嵌入表达式
花括号里可以放任何 JavaScript 表达式:
const price = 100;
const discount = 0.8;
const finalPrice = `最终价格:${price * discount} 元`;
2.4 解构赋值:快速提取数据
解构赋值让你从数组或对象中提取数据变得极其方便。说白了,就是「拆包」。
数组解构
const arr = [1, 2, 3];
const [a, b, c] = arr;
console.log(a, b, c); // 1 2 3
// 跳过元素
const [first, , third] = arr;
console.log(first, third); // 1 3
// 默认值
const [x, y, z = 0] = [1, 2];
console.log(x, y, z); // 1 2 0
对象解构
const user = { name: '李四', age: 30, email: 'li@example.com' };
const { name, age } = user;
console.log(name, age); // 李四 30
// 重命名
const { name: userName, age: userAge } = user;
console.log(userName, userAge); // 李四 30
// 嵌套解构
const data = { person: { name: '王五', address: { city: '北京' } } };
const { person: { address: { city } } } = data;
console.log(city); // 北京
实战经验:我在处理 API 返回数据时,经常用解构赋值直接提取需要的字段。比如 const { data, status } = await axios.get('/api/user'),一行代码搞定。
2.5 展开运算符:合并与复制
展开运算符(...)可以把数组或对象「展开」。它有两个主要用途:复制和合并。
数组展开
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// 合并数组
const merged = [...arr1, ...arr2];
console.log(merged); // [1, 2, 3, 4, 5, 6]
// 复制数组(浅拷贝)
const copy = [...arr1];
copy.push(4);
console.log(arr1); // [1, 2, 3](原数组不变)
对象展开
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
// 合并对象
const mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj); // { a: 1, b: 2, c: 3, d: 4 }
// 覆盖属性
const base = { name: '张三', age: 20 };
const update = { age: 25, email: 'new@example.com' };
const result = { ...base, ...update };
console.log(result); // { name: '张三', age: 25, email: 'new@example.com' }
2.6 模块化:import/export
模块化是现代前端开发的标配。ES6 的 import 和 export 让代码组织变得清晰有序。
导出(export)
// 导出单个变量
export const name = '张三';
// 导出函数
export function sayHello() {
console.log('Hello');
}
// 导出类
export class Person {
constructor(name) {
this.name = name;
}
}
// 默认导出
export default function() {
console.log('默认导出');
}
// 统一导出
const a = 1;
const b = 2;
export { a, b };
导入(import)
// 导入默认导出
import myFunction from './myModule';
// 导入命名导出
import { name, sayHello } from './myModule';
// 导入所有
import * as myModule from './myModule';
console.log(myModule.name);
// 重命名导入
import { name as userName } from './myModule';
// 混合导入
import defaultExport, { namedExport } from './myModule';
| 导出方式 | 导入方式 | 说明 |
|---|---|---|
export default |
import xxx from |
每个模块只能有一个默认导出 |
export { a, b } |
import { a, b } from |
命名导出,可以有多个 |
export const c |
import { c } from |
直接导出声明 |
实战经验:我在项目中通常这样组织:工具函数用命名导出,组件用默认导出。这样既清晰又方便。
import 时,我会把第三方库的导入放在最前面,然后是项目内部模块。这样一眼就能看出依赖关系。
好了,ES6+ 的核心语法就这些。你想想看,这些特性是不是让代码变得更简洁、更易读了?下一章我们会把这些知识用到实际项目中,到时候你就知道它们有多强大了。