ES6特性需理解语义边界:let/const有TDZ而var会变量提升;箭头函数无this/arguments且不可构造;解构默认值对null无效;Promise错误需统一用async/await+try/catch处理。

ES6(ECMAScript 2015)不是“要不要用”的问题,而是你写的代码里很可能已经用了——比如 let、const、箭头函数,但未必清楚它们的边界和陷阱。
let/const 和 var 的实际区别不只是作用域
很多人知道 let 是块级作用域,var 是函数级,但真正影响项目的是变量提升(hoisting)行为和暂时性死区(TDZ):
-
var a = 1声明会被提升,赋值不提升,所以访问未初始化的var变量得undefined -
let b或const c声明也会提升,但**不初始化**,在声明前访问直接抛ReferenceError,不是undefined - 循环中用
var绑定事件监听器,常出现闭包捕获同一变量的问题;改用let就自动为每次迭代创建新绑定
示例:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0); // 输出 3, 3, 3
}
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 0); // 输出 0, 1, 2
}
箭头函数不能替代所有 function 的场景
箭头函数没有自己的 this、arguments、super 或 new.target,这在实际项目中容易翻车:
立即学习“Java免费学习笔记(深入)”;
- 对象方法里写
onClick: () => this.handleClick()→this指向外层作用域,不是当前对象 - Vue 或 React 类组件中,事件回调若用箭头函数,
this无法指向组件实例 - 不能用作构造函数:
new (() => {})报TypeError: xxx is not a constructor - 需要动态
arguments(如参数透传)时,箭头函数拿不到,得回退到function
解构赋值不只是语法糖,它影响默认值和类型安全
解构常用于 props、API 响应、配置对象,但默认值逻辑和嵌套失败处理容易被忽略:
-
const { name = 'guest', age } = user:只有name是undefined才触发默认值,null不算,所以上面写法对{ name: null }依然得到null - 嵌套解构如
const { data: { list } } = response,若response.data不存在,直接报错;需加中间默认值:const { data = {} } = response; const { list } = data; - 函数参数解构 + 默认值是常见模式,但注意:默认值在调用时才计算,适合惰性初始化
示例(安全解构 API 响应):
function handleUser({ id, profile = {}, permissions = [] } = {}) {
const { avatar, nickname } = profile;
return { id, avatar, nickname, canEdit: permissions.includes('edit') };
}
Promise 和 async/await 在错误处理上必须统一策略
混用 .then().catch() 和 try/catch 容易漏掉错误,尤其在深层调用链中:
-
async函数内部抛错会变成 rejected Promise,但await后没try/catch,错误就冒泡到最近的catch或全局unhandledrejection -
Promise.all([p1, p2])中任一 reject 整体 reject;若要“全返回”,得用Promise.allSettled(ES2020,注意兼容性) -
axios 等库的响应拦截器里,
return response.data是常见写法,但若后端返回非 2xx 却没抛错,await仍会进入then分支,需手动检查状态码
建议:项目中统一用 async/await + try/catch,并在封装请求函数时把业务错误(如 401、403)显式转为 throw,避免散落的 if (res.status !== 200) {...}。
ES6 特性不是堆砌语法,关键在理解每个特性的语义边界——比如 const 保证引用不变,但不阻止对象内部属性修改;class 只是语法糖,原型链本质没变。用错地方比不用更难排查。











