modern-javascript
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseModern JavaScript (ES6-ES2025)
现代JavaScript(ES6-ES2025)
Write clean, performant, maintainable JavaScript using modern language features. This skill covers ES6 through ES2025, emphasizing immutability, functional patterns, and expressive syntax.
利用现代语言特性编写简洁、高性能、可维护的JavaScript代码。本技能涵盖ES6至ES2025,强调不可变性、函数式模式和富有表现力的语法。
Quick Decision Trees
快速决策树
"Which array method should I use?"
"我应该使用哪种数组方法?"
What do I need?
├─ Transform each element → .map()
├─ Keep some elements → .filter()
├─ Find one element → .find() / .findLast()
├─ Check if condition met → .some() / .every()
├─ Reduce to single value → .reduce()
├─ Get last element → .at(-1)
├─ Sort without mutating → .toSorted()
├─ Reverse without mutating → .toReversed()
├─ Group by property → Object.groupBy()
└─ Flatten nested arrays → .flat() / .flatMap()我需要做什么?
├─ 转换每个元素 → .map()
├─ 筛选部分元素 → .filter()
├─ 查找单个元素 → .find() / .findLast()
├─ 检查是否满足条件 → .some() / .every()
├─ 归约为单个值 → .reduce()
├─ 获取最后一个元素 → .at(-1)
├─ 排序且不修改原数组 → .toSorted()
├─ 反转且不修改原数组 → .toReversed()
├─ 按属性分组 → Object.groupBy()
└─ 扁平化嵌套数组 → .flat() / .flatMap()"How do I handle nullish values?"
"如何处理空值?"
Nullish handling?
├─ Safe property access → obj?.prop / obj?.[key]
├─ Safe method call → obj?.method?.()
├─ Default for null/undefined only → value ?? 'default'
├─ Default for any falsy → value || 'default'
├─ Assign if null/undefined → obj.prop ??= 'default'
└─ Check property exists → Object.hasOwn(obj, 'key')空值处理?
├─ 安全访问属性 → obj?.prop / obj?.[key]
├─ 安全调用方法 → obj?.method?.()
├─ 仅为null/undefined设置默认值 → value ?? 'default'
├─ 为任何假值设置默认值 → value || 'default'
├─ 仅当为null/undefined时赋值 → obj.prop ??= 'default'
└─ 检查属性是否存在 → Object.hasOwn(obj, 'key')"Should I mutate or copy?"
"应该修改原对象还是创建副本?"
Always prefer non-mutating methods:
├─ Sort array → .toSorted() (not .sort())
├─ Reverse array → .toReversed() (not .reverse())
├─ Splice array → .toSpliced() (not .splice())
├─ Update element → .with(i, val) (not arr[i] = val)
├─ Add to array → [...arr, item] (not .push())
└─ Merge objects → {...obj, key} (not Object.assign())优先选择非修改式方法:
├─ 数组排序 → .toSorted() (而非.sort())
├─ 数组反转 → .toReversed() (而非.reverse())
├─ 数组删除元素 → .toSpliced() (而非.splice())
├─ 更新数组元素 → .with(i, val) (而非arr[i] = val)
├─ 向数组添加元素→ [...arr, item] (而非.push())
└─ 合并对象 → {...obj, key} (而非Object.assign())ES Version Quick Reference
ES版本速查表
| Version | Year | Key Features |
|---|---|---|
| ES6 | 2015 | let/const, arrow functions, classes, destructuring, spread, Promises, modules, Symbol, Map/Set, Proxy, generators |
| ES2016 | 2016 | Array.includes(), exponentiation operator ** |
| ES2017 | 2017 | async/await, Object.values/entries, padStart/padEnd, trailing commas, SharedArrayBuffer, Atomics |
| ES2018 | 2018 | Rest/spread for objects, for await...of, Promise.finally(), RegExp named groups, lookbehind, dotAll flag |
| ES2019 | 2019 | .flat(), .flatMap(), Object.fromEntries(), trimStart/End(), optional catch binding, stable Array.sort() |
| ES2020 | 2020 | Optional chaining ?., nullish coalescing ??, BigInt, Promise.allSettled(), globalThis, dynamic import() |
| ES2021 | 2021 | String.replaceAll(), Promise.any(), logical assignment ??= and or=, numeric separators 1_000_000 |
| ES2022 | 2022 | .at(), Object.hasOwn(), top-level await, private class fields #field, static blocks, Error.cause |
| ES2023 | 2023 | .toSorted(), .toReversed(), .toSpliced(), .with(), .findLast(), .findLastIndex(), hashbang grammar |
| ES2024 | 2024 | Object.groupBy(), Map.groupBy(), Promise.withResolvers(), RegExp v flag, resizable ArrayBuffer |
| ES2025 | 2025 | Iterator helpers (.map, .filter, .take), Set methods (.union, .intersection), RegExp.escape(), using/await using |
| 版本 | 年份 | 关键特性 |
|---|---|---|
| ES6 | 2015 | let/const、箭头函数、类、解构、展开、Promises、模块、Symbol、Map/Set、Proxy、生成器 |
| ES2016 | 2016 | Array.includes()、指数运算符 ** |
| ES2017 | 2017 | async/await、Object.values/entries、padStart/padEnd、尾逗号、SharedArrayBuffer、Atomics |
| ES2018 | 2018 | 对象的剩余/展开、for await...of、Promise.finally()、正则表达式命名组、后行断言、dotAll标志 |
| ES2019 | 2019 | .flat()、.flatMap()、Object.fromEntries()、trimStart/End()、可选catch绑定、稳定的Array.sort() |
| ES2020 | 2020 | 可选链 ?.、空值合并 ??、BigInt、Promise.allSettled()、globalThis、动态import() |
| ES2021 | 2021 | String.replaceAll()、Promise.any()、逻辑赋值 ??= 和 or=、数字分隔符 1_000_000 |
| ES2022 | 2022 | .at()、Object.hasOwn()、顶层await、私有类字段 #field、静态块、Error.cause |
| ES2023 | 2023 | .toSorted()、.toReversed()、.toSpliced()、.with()、.findLast()、.findLastIndex()、hashbang语法 |
| ES2024 | 2024 | Object.groupBy()、Map.groupBy()、Promise.withResolvers()、正则表达式v标志、可调整大小的ArrayBuffer |
| ES2025 | 2025 | 迭代器辅助方法(.map、.filter、.take)、Set方法(.union、.intersection)、RegExp.escape()、using/await using |
Modernization Patterns
现代化模式
Array Access
数组访问
javascript
// ❌ Legacy
const last = arr[arr.length - 1];
const secondLast = arr[arr.length - 2];
// ✅ Modern (ES2022)
const last = arr.at(-1);
const secondLast = arr.at(-2);javascript
// ❌ 遗留写法
const last = arr[arr.length - 1];
const secondLast = arr[arr.length - 2];
// ✅ 现代写法(ES2022)
const last = arr.at(-1);
const secondLast = arr.at(-2);Non-Mutating Array Operations
非修改式数组操作
javascript
// ❌ Mutates original array
const sorted = arr.sort((a, b) => a - b);
const reversed = arr.reverse();
// ✅ Returns new array (ES2023)
const sorted = arr.toSorted((a, b) => a - b);
const reversed = arr.toReversed();
const updated = arr.with(2, 'new value');
const removed = arr.toSpliced(1, 1);javascript
// ❌ 修改原数组
const sorted = arr.sort((a, b) => a - b);
const reversed = arr.reverse();
// ✅ 返回新数组(ES2023)
const sorted = arr.toSorted((a, b) => a - b);
const reversed = arr.toReversed();
const updated = arr.with(2, 'new value');
const removed = arr.toSpliced(1, 1);String Replacement
字符串替换
javascript
// ❌ Legacy with regex
const result = str.replace(/foo/g, 'bar');
// ✅ Modern (ES2021)
const result = str.replaceAll('foo', 'bar');javascript
// ❌ 使用正则表达式的遗留写法
const result = str.replace(/foo/g, 'bar');
// ✅ 现代写法(ES2021)
const result = str.replaceAll('foo', 'bar');Grouping Data
数据分组
javascript
// ❌ Manual grouping
const grouped = items.reduce((acc, item) => {
const key = item.category;
acc[key] = acc[key] || [];
acc[key].push(item);
return acc;
}, {});
// ✅ Modern (ES2024)
const grouped = Object.groupBy(items, item => item.category);javascript
// ❌ 手动分组
const grouped = items.reduce((acc, item) => {
const key = item.category;
acc[key] = acc[key] || [];
acc[key].push(item);
return acc;
}, {});
// ✅ 现代写法(ES2024)
const grouped = Object.groupBy(items, item => item.category);Nullish Handling
空值处理
javascript
// ❌ Falsy check (0, '', false are valid values)
const value = input || 'default';
const name = user && user.profile && user.profile.name;
// ✅ Nullish check (only null/undefined)
const value = input ?? 'default';
const name = user?.profile?.name;javascript
// ❌ 假值检查(0、''、false会被误判)
const value = input || 'default';
const name = user && user.profile && user.profile.name;
// ✅ 空值检查(仅针对null/undefined)
const value = input ?? 'default';
const name = user?.profile?.name;Property Existence
属性存在性检查
javascript
// ❌ Can be fooled by prototype or overwritten hasOwnProperty
if (obj.hasOwnProperty('key')) { }
// ✅ Modern (ES2022)
if (Object.hasOwn(obj, 'key')) { }javascript
// ❌ 可能被原型覆盖或hasOwnProperty被重写
if (obj.hasOwnProperty('key')) { }
// ✅ 现代写法(ES2022)
if (Object.hasOwn(obj, 'key')) { }Logical Assignment
逻辑赋值
javascript
// ❌ Verbose assignment
if (obj.prop === null || obj.prop === undefined) {
obj.prop = 'default';
}
// ✅ Modern (ES2021)
obj.prop ??= 'default'; // Assign if null/undefined
obj.count ||= 0; // Assign if falsy
obj.enabled &&= check(); // Assign if truthyjavascript
// ❌ 冗长的赋值写法
if (obj.prop === null || obj.prop === undefined) {
obj.prop = 'default';
}
// ✅ 现代写法(ES2021)
obj.prop ??= 'default'; // 仅当为null/undefined时赋值
obj.count ||= 0; // 为假值时赋值
obj.enabled &&= check(); // 为真值时赋值Async Patterns
异步模式
Promise Combinators
Promise组合器
javascript
// Wait for all, fail if any fails
const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]);
// Wait for all, get status of each
const results = await Promise.allSettled([fetchA(), fetchB()]);
results.forEach(r => {
if (r.status === 'fulfilled') console.log(r.value);
else console.error(r.reason);
});
// First to succeed
const fastest = await Promise.any([fetchFromCDN1(), fetchFromCDN2()]);
// First to settle
const winner = await Promise.race([fetchData(), timeout(5000)]);javascript
// 等待所有Promise完成,任一失败则整体失败
const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]);
// 等待所有Promise完成,获取每个的状态
const results = await Promise.allSettled([fetchA(), fetchB()]);
results.forEach(r => {
if (r.status === 'fulfilled') console.log(r.value);
else console.error(r.reason);
});
// 等待第一个成功的Promise
const fastest = await Promise.any([fetchFromCDN1(), fetchFromCDN2()]);
// 等待第一个完成的Promise(无论成功或失败)
const winner = await Promise.race([fetchData(), timeout(5000)]);Promise.withResolvers (ES2024)
Promise.withResolvers(ES2024)
javascript
// ❌ Legacy pattern
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
// ✅ Modern (ES2024)
const { promise, resolve, reject } = Promise.withResolvers();javascript
// ❌ 遗留模式
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
// ✅ 现代写法(ES2024)
const { promise, resolve, reject } = Promise.withResolvers();Top-Level Await (ES2022)
顶层Await(ES2022)
javascript
// In ES modules, await at top level
const config = await fetch('/config.json').then(r => r.json());
const db = await connectDatabase(config);
export { db };javascript
// 在ES模块中,可在顶层使用await
const config = await fetch('/config.json').then(r => r.json());
const db = await connectDatabase(config);
export { db };Functional Patterns
函数式模式
Immutable Object Updates
不可变对象更新
javascript
// Add/update property
const updated = { ...user, age: 31 };
// Remove property
const { password, ...userWithoutPassword } = user;
// Nested update
const updated = {
...state,
user: { ...state.user, name: 'New Name' }
};javascript
// 添加/更新属性
const updated = { ...user, age: 31 };
// 删除属性
const { password, ...userWithoutPassword } = user;
// 嵌套更新
const updated = {
...state,
user: { ...state.user, name: 'New Name' }
};Array Transformations
数组转换
javascript
// Chain transformations (ES2023)
const result = users
.filter(u => u.active)
.map(u => u.name)
.toSorted();
// Using flatMap for filter+map (single pass)
const activeNames = users.flatMap(u => u.active ? [u.name] : []);
// ES2024: Group then process
const byStatus = Object.groupBy(users, u => u.active ? 'active' : 'inactive');
const activeNames = byStatus.active?.map(u => u.name) ?? [];javascript
// 链式转换(ES2023)
const result = users
.filter(u => u.active)
.map(u => u.name)
.toSorted();
// 使用flatMap同时完成过滤和映射(单次遍历)
const activeNames = users.flatMap(u => u.active ? [u.name] : []);
// ES2024:先分组再处理
const byStatus = Object.groupBy(users, u => u.active ? 'active' : 'inactive');
const activeNames = byStatus.active?.map(u => u.name) ?? [];Composition
函数组合
javascript
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const processUser = pipe(
user => ({ ...user, name: user.name.trim() }),
user => ({ ...user, email: user.email.toLowerCase() }),
user => ({ ...user, createdAt: new Date() })
);javascript
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const processUser = pipe(
user => ({ ...user, name: user.name.trim() }),
user => ({ ...user, email: user.email.toLowerCase() }),
user => ({ ...user, createdAt: new Date() })
);Destructuring Patterns
解构模式
Object Destructuring
对象解构
javascript
// Basic with rename and default
const { name: userName, age = 18 } = user;
// Nested
const { address: { city, country } } = user;
// Rest
const { id, ...userData } = user;javascript
// 基础用法,支持重命名和默认值
const { name: userName, age = 18 } = user;
// 嵌套解构
const { address: { city, country } } = user;
// 剩余解构
const { id, ...userData } = user;Array Destructuring
数组解构
javascript
// Skip elements
const [first, , third] = array;
// Rest
const [head, ...tail] = array;
// Swap variables
[a, b] = [b, a];
// Function returns
const [x, y] = getCoordinates();javascript
// 跳过元素
const [first, , third] = array;
// 剩余解构
const [head, ...tail] = array;
// 变量交换
[a, b] = [b, a];
// 函数返回值解构
const [x, y] = getCoordinates();Anti-Patterns
反模式
| Anti-Pattern | Problem | Modern Solution |
|---|---|---|
| Verbose, error-prone | |
| Mutates array | |
| Regex overhead | |
| Can be overwritten | |
| 0, '', false treated as falsy | |
| Verbose null checks | |
| Index bugs, verbose | |
| Boilerplate | |
| Manual array grouping | Verbose, error-prone | |
| 反模式 | 问题 | 现代解决方案 |
|---|---|---|
| 冗长且易出错 | |
| 修改原数组 | |
| 正则表达式开销大 | |
| 可能被重写 | |
| `value | default` | |
| 空值检查冗长 | |
| 索引易出错且冗长 | |
| 样板代码过多 | |
| 手动数组分组 | 冗长且易出错 | |
Best Practices
最佳实践
- Use by default — Only use
constwhen reassignment is neededlet - Prefer arrow functions — Especially for callbacks and short functions
- Use template literals — Instead of string concatenation
- Destructure early — Extract what you need at function start
- Avoid mutations — Use ,
.toSorted(), spread operator.toReversed() - Use optional chaining — Prevent "Cannot read property of undefined"
- Use nullish coalescing — for defaults, not
??(unless intentional)|| - Prefer array methods — ,
.map(),.filter()over loops.find() - Use — Instead of
async/awaitchains.then() - Handle errors properly — with async/await
try/catch
- 默认使用—— 仅在需要重新赋值时使用
constlet - 优先使用箭头函数 —— 尤其适用于回调函数和短函数
- 使用模板字面量 —— 替代字符串拼接
- 尽早解构 —— 在函数开头提取所需内容
- 避免修改原对象 —— 使用、
.toSorted()、展开运算符.toReversed() - 使用可选链 —— 避免出现“Cannot read property of undefined”错误
- 使用空值合并运算符 —— 用设置默认值,而非
??(除非故意为之)|| - 优先使用数组方法 —— 用、
.map()、.filter()替代循环.find() - 使用—— 替代
async/await链式调用.then() - 正确处理错误 —— 结合使用
async/awaittry/catch
Reference Documentation
参考文档
ES Version References
ES版本参考
| File | Purpose |
|---|---|
| references/ES2016-ES2017.md | includes, async/await, Object.values/entries, string padding |
| references/ES2018-ES2019.md | rest/spread objects, flat/flatMap, RegExp named groups |
| references/ES2022-ES2023.md | .at(), .toSorted(), .toReversed(), .findLast(), class features |
| references/ES2024.md | Object.groupBy, Promise.withResolvers, RegExp v flag |
| references/ES2025.md | Set methods, iterator helpers, using/await using |
| references/UPCOMING.md | Temporal API, Decorators, Decorator Metadata |
| 文件 | 用途 |
|---|---|
| references/ES2016-ES2017.md | includes、async/await、Object.values/entries、字符串填充 |
| references/ES2018-ES2019.md | 对象的剩余/展开、flat/flatMap、正则表达式命名组 |
| references/ES2022-ES2023.md | .at()、.toSorted()、.toReversed()、.findLast()、类特性 |
| references/ES2024.md | Object.groupBy、Promise.withResolvers、正则表达式v标志 |
| references/ES2025.md | Set方法、迭代器辅助方法、using/await using |
| references/UPCOMING.md | Temporal API、装饰器、装饰器元数据 |
Pattern References
模式参考
| File | Purpose |
|---|---|
| references/PROMISES.md | Promise fundamentals, async/await, combinators |
| references/CONCURRENCY.md | Parallel, batched, pool patterns, retry, cancellation |
| references/IMMUTABILITY.md | Immutable data patterns, pure functions |
| references/COMPOSITION.md | Higher-order functions, memoization, monads |
| references/CHEATSHEET.md | Quick syntax reference |
| 文件 | 用途 |
|---|---|
| references/PROMISES.md | Promise基础、async/await、组合器 |
| references/CONCURRENCY.md | 并行、批处理、池化模式、重试、取消 |
| references/IMMUTABILITY.md | 不可变数据模式、纯函数 |
| references/COMPOSITION.md | 高阶函数、记忆化、单子 |
| references/CHEATSHEET.md | 快速语法参考 |
Resources
资源
Specifications
规范
- ECMAScript Specification: https://tc39.es/ecma262/ (living standard)
- TC39 Proposals: https://github.com/tc39/proposals (upcoming features)
- TC39 Process: https://tc39.es/process-document/ (how features are added)
- ECMAScript规范: https://tc39.es/ecma262/(现行标准)
- TC39提案: https://github.com/tc39/proposals(即将推出的特性)
- TC39流程: https://tc39.es/process-document/(特性添加流程)
Documentation
文档
- MDN Web Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript
- JavaScript.info: https://javascript.info/
- MDN Web Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript
- JavaScript.info: https://javascript.info/
Compatibility
兼容性
- Can I Use: https://caniuse.com (browser support tables)
- Node.js ES Compatibility: https://node.green/
- Can I Use: https://caniuse.com(浏览器支持表)
- Node.js ES兼容性: https://node.green/