16. JavaScript ES6+ 哪些常用新特性?

189 阅读1分钟

JavaScript ES6+ 哪些常用新特性?

1 模板字符串(`

使用 反引号`)包裹,支持 嵌入变量表达式多行字符串

1.1 嵌入 变量

// 示例代码 1
const name = "张三";
const age = 25;
const message = `
你好,我的名字是 ${name}。
我今年 ${age} 岁。
我喜欢编程。
`;

console.log(message);
/*
你好,我的名字是 张三。
我今年 25 岁。
我喜欢编程。
*/

1.2 嵌入 函数或表达式

// 示例代码 2
const add = (a, b) => a + b;

const result = `
计算 5 + 10 的结果是:${add(5, 10)}
`;

console.log(result);

1.3 嵌入 多行字符串

// 示例代码 3
const multiLineString = `
这是第一行
这是第二行
这是第三行
`;

console.log(multiLineString);
/* 
这是第一行
这是第二行
这是第三行
*/

2 对象字面量增强(Enhanced Object Literals)

允许直接使用 变量 作为 对象属性名方法名

// 示例代码 4
const name = "Alice";
const age = 25;

const obj = {
    name, // 属性名简写,等价于 name: name
    age,  // 属性名简写,等价于 age: age

    // 方法简写
    greet() {
        return `Hello, ${this.name}`;
    }
    /*
    等价于
    greet: function() { 
        return `Hello, ${this.name}`; 
    }
    */
};

console.log(obj.name);   // 输出:Alice
console.log(obj.age);    // 输出:25
console.log(obj.greet()); // 输出:Hello, Alice

3 模块化(Modules)

模块化 是 现代编程中 一种重要的 组织代码方式,它将代码分割为 独立的可重用 的 模块,每个模块 通常实现 一个特定的 功能逻辑

使用 importexport 实现 模块化。

3.1 主要使用场景

1 代码组织和复用
  • 大型 项目开发:当 代码量 较大时,将功能 分解为 多个模块 可以提升 代码的 可读性 和 可维护性。
  • 跨项目 共享 代码:通用功能模块(如 工具函数库API 封装 等)可以在 多个项目中 复用
// 示例代码 5
// math.js
export const add = (a, b) => a + b;

// main.js
import { add } from "./math.js";
console.log(add(2, 3)); // 输出:5
2 分离关注点
  • 前端 项目开发:将 业务逻辑视图渲染样式管理 分离到 不同的模块。
  • 后端 项目开发:分离 路由控制器服务层代码,保持 逻辑独立。
// 示例代码 6
// api.js
export async function fetchData(url) {
    const response = await fetch(url);
    return await response.json();
}

// component.js
import { fetchData } from './api.js';
fetchData('/api/data').then(data => console.log(data));
3 团队协作
  • 多人协作开发时,不同开发者 负责 不同的模块减少 代码冲突 的风险。

  • 通过 模块接口 清晰地定义 输入输出,每个开发者 专注于 自己的 模块实现。

// 示例代码 7
// 前端开发中,一个人负责 UI 组件模块,另一个人负责状态管理模块,通过模块接口进行协作
// uiComponent.js
export const renderButton = () => {
    console.log('Rendering button');
};

// stateManager.js
export const updateState = (newState) => {
    console.log('Updating state to', newState);
};

【具体实例代码,等待同步......】

4 按需加载(代码分割)
  • 在 Web 应用中,按需加载模块(即代码分割)可以 减少 首次加载时间提升性能
  • 只加载 当前页面 或 功能所需的 代码,而不是 一次性加载 所有模块。
// 示例代码 8
// 动态导入模块
// mathUtils.js
export function add(a, b) {
    return a + b;
}

export function subtract(a, b) {
    return a - b;
}

// main.js
const loadMathUtils = async () => {
    // 动态导入模块
    const mathUtils = await import('./mathUtils.js');
    console.log(mathUtils.add(2, 3)); // 输出:5
    console.log(mathUtils.subtract(5, 2)); // 输出:3
};

document.querySelector('#loadBtn').addEventListener('click', loadMathUtils);

在其他模块中,只能访问 publicFunction,无法访问 privateVar

5 提升代码安全性
  • 避免 全局变量 冲突,将代码 封装在 模块内。
  • 控制 模块的 导出内容,隐藏 不需要 暴露的 实现细节。
// 示例代码 9
// myModule.js
const privateVar = 'This is private';
export const publicFunction = () => console.log('This is public');
6 第三方库的集成
  • 通过 模块化方式 引入 和 管理 第三方依赖(如 lodash、axios 等)。
  • 管理 依赖版本,减少 全局污染。
// 示例代码 10
// 使用 import 从 npm 包中加载模块:
import _ from 'lodash';
console.log(_.chunk([1, 2, 3, 4], 2)); // 输出:[[1, 2], [3, 4]]
7 测试与调试
  • 将代码 分解为 小模块,有助于进行 单元测试调试
  • 可以针对 每个模块 独立编写 测试用例,提高 测试 覆盖率
// 示例代码 11
// 单独测试工具模块:
// mathUtils.test.js
import { add } from './mathUtils.js';
test('add function', () => {
    expect(add(2, 3)).toBe(5);
});

4 Set / Map

SetMap 是 ES6 引入的 两种 新 数据结构,分别用于 存储 唯一值集合键值对 的 映射关系。

SetMap 的操作(如 查找插入删除)在多数情况下 比 普通对象 和 数组 更快,尤其是当 数据量 很大时

4.1 Set

Set 是一个 集合,它存储的是 唯一值。它可以是 任何类型 的值(数字字符串对象等)。

// 示例代码 6
const mySet = new Set([1, 2, 3, 3, 4]);
console.log(mySet); // 输出:Set(4) { 1, 2, 3, 4 }

// 遍历 Set
for (let value of mySet) {
    console.log(value); // 输出:1, 2, 3
}

mySet.forEach(value => console.log(value)); // 输出:1, 2, 3
Set 和 数组 转换
// 示例代码 7
// 数组 转 Set
const arr = [1, 2, 2, 3];
const mySet = new Set(arr); // 去重
console.log([...mySet]);    // 输出:[1, 2, 3]

// Set 转 数组
const mySet = new Set([1, 2, 3]);
const arr = Array.from(mySet);
console.log(arr); // 输出:[1, 2, 3]

4.2 Map

Map 是一种** 键值对 集合**,其中 可以是 任意数据类型。与 普通对象 不同,Map 保留 键值对 的 插入顺序

// 示例代码 8
const myMap = new Map();
myMap.set('name', 'Alice'); // 设置键值对
myMap.set('age', 25);       // 设置键值对

// 遍历 Map
for (let [key, value] of myMap) {
    console.log(`${key}: ${value}`); // 输出:name: Alice, age: 25
}

myMap.forEach((value, key) => console.log(`${key}: ${value}`));
// 输出:name: Alice, age: 25
Map 和 对象 转换
// 示例代码 9
// 对象 转 Map
const obj = { name: 'Alice', age: 25 };
const myMap = new Map(Object.entries(obj));
console.log(myMap); // 输出:Map(2) { 'name' => 'Alice', 'age' => 25 }

// Map 转 对象
const myMap = new Map([['name', 'Alice'], ['age', 25]]);
const obj = Object.fromEntries(myMap);
console.log(obj); // 输出:{ name: 'Alice', age: 25 }

5 Class 语法(Class Syntax)

提供了更接近 传统 面向对象编程继承 语法。

// 示例代码 10
class Person {
    constructor(name) {
        this.name = name;
    }
    greet() {
        return `Hello, ${this.name}`;
    }
}

class Student extends Person {
    constructor(name, grade) {
        super(name);
        this.grade = grade;
    }
}