ES6+ 新特性精讲:箭头函数、解构与模块
ES6+ 新特性精讲:箭头函数、解构与模块
ES6(ECMAScript 2015)及其后续版本为 JavaScript 带来了大量简洁、强大的新特性,其中箭头函数、解构赋值和模块化是日常开发中使用频率最高的三个。本文将深入浅出地讲解它们的用法与注意事项。
箭头函数
箭头函数提供了一种比传统函数表达式更简短的语法,并且它不会创建自己的 this 上下文。
基本语法
// 传统函数
const add = function(a, b) {
return a + b;
};
// 箭头函数
const addArrow = (a, b) => a + b;
- 如果只有一个参数,可以省略参数外的圆括号。
- 如果函数体只有一条
return语句,可以省略花括号和return关键字。 - 如果没有参数或有多个参数,必须使用圆括号。
const greet = name => `你好,${name}`; // 单参数省略括号
const sayHello = () => console.log('Hello'); // 无参数需要括号
const sum = (a, b) => a + b; // 多参数需要括号
返回对象字面量
直接返回对象时,需要将对象包裹在圆括号内,否则花括号会被解释为函数体。
// 错误:花括号被当成函数体
const user = (name, age) => { name, age }; // undefined
// 正确:用圆括号包裹对象
const user = (name, age) => ({ name, age });
this 的绑定规则
箭头函数最大的特点是没有自己的 this,它会捕获外层作用域的 this 值。这一特性使其在回调函数和事件处理中极其有用。
const button = document.querySelector('button');
// 传统函数中,this 指向触发的元素
button.addEventListener('click', function() {
console.log(this); // <button> 元素
});
// 箭头函数中,this 继承自外层作用域
button.addEventListener('click', () => {
console.log(this); // 外层作用域的 this(例如 window)
});
在对象方法中,使用箭头函数时要小心,因为它会使 this 指向定义时的外层上下文,而非调用时的对象。
const obj = {
name: 'Alice',
greet: () => {
console.log(`你好,我是 ${this.name}`); // this 指向全局,输出 undefined
}
};
obj.greet(); // 你好,我是 undefined
何时避免箭头函数
- 对象的方法(尤其是需要动态
this时) - 构造函数(箭头函数不能使用
new) - 需要
arguments对象的函数(箭头函数没有arguments) - 原型上添加方法
箭头函数是词法作用域的绑定工具,理解它的 this 规则是掌握 ES6 的关键一步。
解构赋值
解构赋值可以从数组或对象中快速提取值并赋给变量,让代码更简洁。
数组解构
按照位置对应提取值:
const colors = ['红', '绿', '蓝'];
const [first, second, third] = colors;
console.log(first); // 红
console.log(third); // 蓝
// 跳过元素、设置默认值
const [, secondColor] = colors; // secondColor = '绿'
const [a, b, c, d = '黄'] = colors; // d 取默认值 '黄'
交换变量变得异常简单:
let x = 1, y = 2;
[x, y] = [y, x];
console.log(x); // 2
console.log(y); // 1
对象解构
通过属性名匹配,顺序无关紧要:
const user = {
name: 'Bob',
age: 25,
city: '北京'
};
const { name, age } = user;
console.log(name); // Bob
console.log(age); // 25
// 重命名变量
const { name: userName, city: location } = user;
console.log(userName); // Bob
console.log(location); // 北京
// 默认值
const { hobby = '阅读' } = user;
console.log(hobby); // 阅读
嵌套解构
对于复杂结构,可以轻松提取深层数据:
const response = {
data: {
user: {
id: 1,
profile: {
avatar: 'avatar.jpg'
}
}
}
};
const { data: { user: { profile: { avatar } } } } = response;
console.log(avatar); // avatar.jpg
函数参数中的解构
直接解构函数参数,避免 obj.xxx 的重复书写,并支持默认值。
function printUser({ name, age = 18, city = '未知' }) {
console.log(`${name},${age}岁,来自${city}`);
}
printUser({ name: 'Carol', city: '上海' });
// 输出:Carol,18岁,来自上海
ES 模块
ES6 正式引入了原生的模块系统,每个文件可以作为一个独立的模块,通过 export 暴露接口,通过 import 引入依赖。
导出(Export)
命名导出:可以导出多个变量、函数或类。
// mathUtils.js
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export class Calculator {
// ...
}
也可以一次性导出:
const PI = 3.14159;
function add(a, b) { return a + b; }
export { PI, add };
默认导出:每个模块只能有一个默认导出,通常用于导出主体功能。
// userService.js
export default class UserService {
constructor() { /* ... */ }
}
或
// config.js
const apiKey = 'secret';
export default apiKey;
导入(Import)
导入命名导出:必须使用与导出时相同的名称,并包裹在花括号中。
import { PI, add } from './mathUtils.js';
console.log(add(2, 3)); // 5
导入默认导出:可以自由命名。
import UserService from './userService.js';
const service = new UserService();
混合导入:
import React, { useState, useEffect } from 'react';
使用别名:
import { reallyLongFunctionName as fn } from './utils.js';
fn();
整体导入:将模块所有导出放到一个命名空间对象中。
import * as math from './mathUtils.js';
console.log(math.PI);
console.log(math.add(1, 2));
模块加载与执行
- 现代浏览器通过
<script type="module">标签支持 ES 模块,并自动采用严格模式('use strict')。 - 模块默认是延迟加载的,相当于
defer属性,不会阻塞 HTML 解析。 - Node.js 环境中,需要将文件后缀改为
.mjs或在package.json中设置"type": "module"。
动态导入 import()
ES2020 引入了动态导入语法,返回一个 Promise,适合按需加载。
// 传统静态导入
import { heavyFunction } from './heavyModule.js';
// 动态导入,仅在需要时加载
const btn = document.getElementById('load-module');
btn.addEventListener('click', async () => {
const module = await import('./heavyModule.js');
module.heavyFunction();
});
这对于代码分割、性能优化非常有用。
总结
- 箭头函数:简洁语法,没有自己的
this,适合回调,但避免用于对象方法和构造函数。 - 解构赋值:优雅地从数组和对象中提取数据,可嵌套、可设默认值,函数参数解构让接口更清晰。
- ES 模块:原生模块化方案,通过
export/import组织代码,支持默认导出、命名导出、动态导入,是现代前端工程的基石。
掌握这三项核心特性,能让你写出更简洁、更具可读性和可维护性的现代 JavaScript 代码。在日常开发中多多实践,逐渐内化这些语法习惯。