在学习完 JavaScript 的基础语法(如变量、条件判断、DOM 操作)后,我们往往会直接进入前端框架(如 Vue、React)或网络请求(如 Fetch)的学习。
但在这个过程中,很多初学者会遇到一个巨大的语法断层。现代前端代码中充斥着类似 const { data } = res、...obj、() => {}、async/await 这样的写法,这些其实都是 ES6(ECMAScript 2015)及以后版本 引入的新特性。
这篇文章旨在帮你夯实这层“隐形地基”,彻底扫清阅读现代 JS 源码时的语法障碍。
1. 箭头函数:更简洁的函数写法
传统 JavaScript 中定义函数使用 function 关键字:
function add(a, b) {
return a + b;
}
ES6 引入了箭头函数 (=>),让代码更加紧凑:
// 基础写法
const add = (a, b) => {
return a + b;
};
// 如果函数体只有一行 return 语句,可以省略大括号和 return 关键字
const multiply = (a, b) => a * b;
// 如果只有一个参数,连小括号都可以省略
const square = x => x * x;
💡 注意: 箭头函数除了写法简洁,还有一个非常重要的特性:它没有自己的
this,它的this永远指向它定义时所在的上下文环境。这在很多回调函数中能解决this指向丢失的问题。
2. 解构赋值:优雅地提取数据
解构赋值允许我们按照一定的模式,从数组或对象中提取值,直接赋值给变量。这是在 Vue 组件和处理接口数据时最常用的语法。
2.1 对象的解构
以前我们从对象中取值需要这样写:
const user = { name: 'Alice', age: 20, city: 'Beijing' };
const name = user.name;
const age = user.age;
现在可以这样写(变量名必须和对象的属性名一致):
const user = { name: 'Alice', age: 20, city: 'Beijing' };
// 一行代码提取 name 和 age
const { name, age } = user;
console.log(name); // "Alice"
2.2 数组的解构
数组解构是按顺序提取的:
const numbers = [10, 20, 30];
// 按位置提取数组中的值
const [first, second] = numbers;
console.log(first); // 10
console.log(second); // 20
3. 展开运算符(Spread Operator)
展开运算符是三个点 ...。它可以在函数调用/数组构造时,将数组表达式或者 string 在语法层面展开;还可以在构造字面量对象时,将对象表达式按 key-value 的方式展开。
3.1 数组的展开与合并
const arr1 = [1, 2];
const arr2 = [3, 4];
// 合并数组,以前用 arr1.concat(arr2)
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4]
// 复制数组(浅拷贝)
const copy = [...arr1];
3.2 对象的展开与合并
在 Vuex 或 Pinia 的状态管理,或者传递 API 参数时非常常见:
const user = { name: 'Bob', age: 25 };
// 复制对象,并添加/覆盖新属性
const updatedUser = {
...user,
age: 26,
job: 'Developer'
};
console.log(updatedUser);
// { name: 'Bob', age: 26, job: 'Developer' }
4. 异步编程:彻底理解 Promise
JavaScript 是单线程执行的。如果某段代码需要等待很长时间(例如网络请求、读取文件),它就会阻塞后续代码的运行,导致页面卡死。为了解决这个问题,JS 采用了异步编程机制。
过去处理异步,主要靠回调函数(Callback),但这容易导致层层嵌套的“回调地狱(Callback Hell)”。于是,ES6 引入了 Promise。
4.1 什么是 Promise?
Promise 就像是一张“承诺凭证”。想象你去奶茶店点单,店员给你一个小票(Promise 对象)。这时候奶茶还没做好(处于 pending 状态),你可以去干别的事。
- 当奶茶做好了,店员叫你的号,这就叫 兑现(fulfilled/resolved)。
- 如果机器坏了做不了,店员告诉你退款,这就叫 拒绝(rejected)。
4.2 基本用法:.then() 和 .catch()
// 假设 fetchData 返回一个 Promise
fetchData()
.then(data => {
// 当 Promise 成功兑现时,执行这里
console.log("获取成功", data);
})
.catch(error => {
// 当 Promise 被拒绝时,执行这里
console.log("出错了", error);
})
.finally(() => {
// 无论成功还是失败,最后都会执行这里(比如用来隐藏 loading 动画)
console.log("请求结束");
});
5. 异步终极方案:async / await
虽然 Promise 解决了回调地狱,但用一堆 .then() 链式调用,代码看着还是不够像“正常”的同步代码。
于是 ES8 (ECMAScript 2017) 推出了 async 和 await,它们是基于 Promise 的语法糖,能让我们用写同步代码的方式来写异步逻辑。
5.1 核心规则
async用于声明一个异步函数,该函数会隐式地返回一个 Promise。await只能在async函数内部使用。它会暂停代码在这个位置的执行,直到后面的 Promise 完成并返回结果,然后再往下走。
5.2 代码对比
用 .then() 写法(Fetch 请求):
function getUser() {
// fetch 本身返回一个 Promise
fetch('https://api.example.com/user')
// 第一步:把响应体解析成 JSON
.then(res => res.json())
// 第二步:拿到真正的数据对象
.then(data => {
console.log(data);
});
}
用 async / await 写法:
async function getUser() {
try {
// 代码会在这里等待 fetch 完成
const res = await fetch('https://api.example.com/user');
// 代码会在这里等待 json 解析完成
const data = await res.json();
console.log(data);
} catch (error) {
// 使用 try...catch 来捕获异常
console.error("请求失败", error);
}
}
可以明显看到,使用 async/await 后,没有了回调函数的嵌套,代码阅读起来是从上往下直线的,非常清晰。
掌握了箭头函数、解构赋值、展开运算符以及 async/await,你就彻底拿到了阅读现代前端代码的“通行证”。接下来再去学习 Vue 3 或网络请求,将会如履平地。