modern-javascript

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Modern 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版本速查表

VersionYearKey Features
ES62015let/const, arrow functions, classes, destructuring, spread, Promises, modules, Symbol, Map/Set, Proxy, generators
ES20162016Array.includes(), exponentiation operator **
ES20172017async/await, Object.values/entries, padStart/padEnd, trailing commas, SharedArrayBuffer, Atomics
ES20182018Rest/spread for objects, for await...of, Promise.finally(), RegExp named groups, lookbehind, dotAll flag
ES20192019.flat(), .flatMap(), Object.fromEntries(), trimStart/End(), optional catch binding, stable Array.sort()
ES20202020Optional chaining ?., nullish coalescing ??, BigInt, Promise.allSettled(), globalThis, dynamic import()
ES20212021String.replaceAll(), Promise.any(), logical assignment ??= and or=, numeric separators 1_000_000
ES20222022.at(), Object.hasOwn(), top-level await, private class fields #field, static blocks, Error.cause
ES20232023.toSorted(), .toReversed(), .toSpliced(), .with(), .findLast(), .findLastIndex(), hashbang grammar
ES20242024Object.groupBy(), Map.groupBy(), Promise.withResolvers(), RegExp v flag, resizable ArrayBuffer
ES20252025Iterator helpers (.map, .filter, .take), Set methods (.union, .intersection), RegExp.escape(), using/await using
版本年份关键特性
ES62015let/const、箭头函数、类、解构、展开、Promises、模块、Symbol、Map/Set、Proxy、生成器
ES20162016Array.includes()、指数运算符 **
ES20172017async/await、Object.values/entries、padStart/padEnd、尾逗号、SharedArrayBuffer、Atomics
ES20182018对象的剩余/展开、for await...of、Promise.finally()、正则表达式命名组、后行断言、dotAll标志
ES20192019.flat()、.flatMap()、Object.fromEntries()、trimStart/End()、可选catch绑定、稳定的Array.sort()
ES20202020可选链 ?.、空值合并 ??、BigInt、Promise.allSettled()、globalThis、动态import()
ES20212021String.replaceAll()、Promise.any()、逻辑赋值 ??= 和 or=、数字分隔符 1_000_000
ES20222022.at()、Object.hasOwn()、顶层await、私有类字段 #field、静态块、Error.cause
ES20232023.toSorted()、.toReversed()、.toSpliced()、.with()、.findLast()、.findLastIndex()、hashbang语法
ES20242024Object.groupBy()、Map.groupBy()、Promise.withResolvers()、正则表达式v标志、可调整大小的ArrayBuffer
ES20252025迭代器辅助方法(.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 truthy
javascript
// ❌ 冗长的赋值写法
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-PatternProblemModern Solution
arr[arr.length-1]
Verbose, error-prone
arr.at(-1)
.sort()
on original
Mutates array
.toSorted()
.replace(/g/)
for all
Regex overhead
.replaceAll()
obj.hasOwnProperty()
Can be overwritten
Object.hasOwn()
value || default
0, '', false treated as falsy
value ?? default
obj && obj.prop && obj.prop.method()
Verbose null checks
obj?.prop?.method?.()
for (let i = 0; ...)
Index bugs, verbose
.map()
,
.filter()
,
for...of
new Promise((res, rej) => ...)
Boilerplate
Promise.withResolvers()
Manual array groupingVerbose, error-prone
Object.groupBy()
反模式问题现代解决方案
arr[arr.length-1]
冗长且易出错
arr.at(-1)
.sort()
修改原数组
修改原数组
.toSorted()
.replace(/g/)
全局替换
正则表达式开销大
.replaceAll()
obj.hasOwnProperty()
可能被重写
Object.hasOwn()
`valuedefault`
obj && obj.prop && obj.prop.method()
空值检查冗长
obj?.prop?.method?.()
for (let i = 0; ...)
循环
索引易出错且冗长
.map()
、
.filter()
、
for...of
new Promise((res, rej) => ...)
样板代码过多
Promise.withResolvers()
手动数组分组冗长且易出错
Object.groupBy()

Best Practices

最佳实践

  1. Use
    const
    by default
    — Only use
    let
    when reassignment is needed
  2. Prefer arrow functions — Especially for callbacks and short functions
  3. Use template literals — Instead of string concatenation
  4. Destructure early — Extract what you need at function start
  5. Avoid mutations — Use
    .toSorted()
    ,
    .toReversed()
    , spread operator
  6. Use optional chaining — Prevent "Cannot read property of undefined"
  7. Use nullish coalescing —
    ??
    for defaults, not
    ||
    (unless intentional)
  8. Prefer array methods —
    .map()
    ,
    .filter()
    ,
    .find()
    over loops
  9. Use
    async/await
    — Instead of
    .then()
    chains
  10. Handle errors properly —
    try/catch
    with async/await
  1. 默认使用
    const
    —— 仅在需要重新赋值时使用
    let
  2. 优先使用箭头函数 —— 尤其适用于回调函数和短函数
  3. 使用模板字面量 —— 替代字符串拼接
  4. 尽早解构 —— 在函数开头提取所需内容
  5. 避免修改原对象 —— 使用
    .toSorted()
    、
    .toReversed()
    、展开运算符
  6. 使用可选链 —— 避免出现“Cannot read property of undefined”错误
  7. 使用空值合并运算符 —— 用
    ??
    设置默认值,而非
    ||
    (除非故意为之)
  8. 优先使用数组方法 —— 用
    .map()
    、
    .filter()
    、
    .find()
    替代循环
  9. 使用
    async/await
    —— 替代
    .then()
    链式调用
  10. 正确处理错误 —— 结合
    async/await
    使用
    try/catch

Reference Documentation

参考文档

ES Version References

ES版本参考

FilePurpose
references/ES2016-ES2017.mdincludes, async/await, Object.values/entries, string padding
references/ES2018-ES2019.mdrest/spread objects, flat/flatMap, RegExp named groups
references/ES2022-ES2023.md.at(), .toSorted(), .toReversed(), .findLast(), class features
references/ES2024.mdObject.groupBy, Promise.withResolvers, RegExp v flag
references/ES2025.mdSet methods, iterator helpers, using/await using
references/UPCOMING.mdTemporal API, Decorators, Decorator Metadata
文件用途
references/ES2016-ES2017.mdincludes、async/await、Object.values/entries、字符串填充
references/ES2018-ES2019.md对象的剩余/展开、flat/flatMap、正则表达式命名组
references/ES2022-ES2023.md.at()、.toSorted()、.toReversed()、.findLast()、类特性
references/ES2024.mdObject.groupBy、Promise.withResolvers、正则表达式v标志
references/ES2025.mdSet方法、迭代器辅助方法、using/await using
references/UPCOMING.mdTemporal API、装饰器、装饰器元数据

Pattern References

模式参考

FilePurpose
references/PROMISES.mdPromise fundamentals, async/await, combinators
references/CONCURRENCY.mdParallel, batched, pool patterns, retry, cancellation
references/IMMUTABILITY.mdImmutable data patterns, pure functions
references/COMPOSITION.mdHigher-order functions, memoization, monads
references/CHEATSHEET.mdQuick syntax reference
文件用途
references/PROMISES.mdPromise基础、async/await、组合器
references/CONCURRENCY.md并行、批处理、池化模式、重试、取消
references/IMMUTABILITY.md不可变数据模式、纯函数
references/COMPOSITION.md高阶函数、记忆化、单子
references/CHEATSHEET.md快速语法参考

Resources

资源

Specifications

规范

Documentation

文档

Compatibility

兼容性