JavaScript 作为世界上最流行的编程语言之一,一直在不断发展和进化。从 2016 年的 ES7 到 2024 年的 ES15,每年都会有新的语言特性和功能被添加进来。这些更新不仅提升了语言的表达能力,也为开发者提供了更多便利的工具和更优雅的解决方案。
本文将按时间顺序,详细介绍从 ES2016 到 ES2024 各个版本中引入的重要特性。
Array.prototype.includes
详细讲解:
array.includes(searchElement[, fromIndex])
searchElement
:要查找的元素fromIndex
(可选):开始搜索的位置索引。默认为0NaN
,而 indexOf
不能indexOf
,返回值更直观(布尔值 vs 索引值)-1
表示从末尾开始undefined
和 null
也能正确处理代码示例:
const numbers = [1, 2, 3, NaN, undefined, null];
// 基础用法
numbers.includes(2); // true
numbers.includes(4); // false
// 处理特殊值
numbers.includes(NaN); // true
numbers.includes(undefined); // true
numbers.includes(null); // true
// 指定起始位置
numbers.includes(1, 1); // false,从索引1开始查找
numbers.includes(3, -2); // false,从倒数第2个元素开始查找
应用场景:
const userPermissions = ['read', 'write', 'delete'];
function canUserDelete() {
return userPermissions.includes('delete');
}
const validTypes = ['jpg', 'png', 'gif'];
function isValidFileType(filename) {
const extension = filename.split('.').pop().toLowerCase();
return validTypes.includes(extension);
}
// 旧写法
if (status === 'pending' || status === 'processing' || status === 'waiting') {
// ...
}
// 新写法
const loadingStates = ['pending', 'processing', 'waiting'];
if (loadingStates.includes(status)) {
// ...
}
**
详细讲解:
Math.pow()
base ** exponent
**=
)代码示例:
// 基础用法
2 ** 3; // 8
3 ** 2; // 9
// 与赋值运算符组合
let x = 2;
x **= 3; // x = 8
// 优先级示例
2 ** 3 * 2; // 16 (先计算 2^3,再乘以 2)
2 * 3 ** 2; // 18 (先计算 3^2,再乘以 2)
// 负数底数
(-2) ** 2; // 4
// -2 ** 2; // 语法错误,需要括号
// 小数指数
8 ** (1/3); // 2 (立方根)
16 ** 0.5; // 4 (平方根)
// 右结合性
2 ** 3 ** 2; // 512 (等同于 2 ** (3 ** 2))
应用场景:
// 计算圆面积
const getCircleArea = radius => Math.PI * (radius ** 2);
// 计算复利
const compound = (principal, rate, years) => {
return principal * ((1 + rate) ** years);
};
// 3D缩放变换
const scale3d = (x, y, z, factor) => ({
x: x * (factor ** 1),
y: y * (factor ** 1),
z: z * (factor ** 1)
});
// 二次方缓动
const easeQuadratic = progress => progress ** 2;
// 三次方缓动
const easeCubic = progress => progress ** 3;
Object.values()
/ Object.entries()
详细讲解:
Object.values()
:返回对象自身所有可枚举属性的值的数组Object.entries()
:返回对象自身所有可枚举属性的键值对数组Object.values(obj)
Object.entries(obj)
代码示例:
// Object.values() 示例
const person = {
name: 'Alice',
age: 30,
role: 'developer'
};
Object.values(person); // ['Alice', 30, 'developer']
// 数字键排序
const obj = { 2: 'b', 1: 'a', 3: 'c' };
Object.values(obj); // ['a', 'b', 'c']
// 处理特殊类型
Object.values('hello'); // ['h', 'e', 'l', 'l', 'o']
Object.values(100); // []
// Object.entries() 示例
Object.entries(person);
// [
// ['name', 'Alice'],
// ['age', 30],
// ['role', 'developer']
// ]
应用场景:
// 对象转Map
const obj = { key1: 'value1', key2: 'value2' };
const map = new Map(Object.entries(obj));
// 对象转FormData
const formData = new FormData();
Object.entries(obj).forEach(([key, value]) => {
formData.append(key, value);
});
// 计算对象值的总和
const scores = { math: 95, english: 88, science: 92 };
const total = Object.values(scores).reduce((sum, score) => sum + score, 0);
// 对象值过滤
const filtered = Object.entries(scores)
.filter(([_, score]) => score >= 90)
.reduce((obj, [subject, score]) => {
obj[subject] = score;
return obj;
}, {});
// 转换为图表数据格式
const data = {
'Q1': 1000,
'Q2': 1500,
'Q3': 1200,
'Q4': 2000
};
const chartData = {
labels: Object.keys(data),
values: Object.values(data)
};
async/await
详细讲解:
async
:声明异步函数,总是返回 Promiseawait
:暂停执行,等待 Promise 解决代码示例:
// 基本使用
async function fetchUserData(userId) {
try {
const user = await fetch(`/api/users/${userId}`);
const posts = await fetch(`/api/posts?userId=${userId}`);
return {
user: await user.json(),
posts: await posts.json()
};
} catch (error) {
console.error('Error fetching user data:', error);
throw error;
}
}
// 并行执行
async function fetchMultipleUsers(userIds) {
const promises = userIds.map(id => fetch(`/api/users/${id}`));
const users = await Promise.all(promises);
return await Promise.all(users.map(user => user.json()));
}
// 循环中的异步操作
async function processItems(items) {
// 串行执行
for (const item of items) {
await processItem(item);
}
// 并行执行
await Promise.all(items.map(processItem));
}
应用场景:
async function uploadFile(file) {
try {
// 1. 获取上传URL
const { uploadUrl } = await getUploadUrl();
// 2. 上传文件
const response = await fetch(uploadUrl, {
method: 'PUT',
body: file
});
// 3. 确认上传
if (response.ok) {
await confirmUpload(file.name);
}
return response;
} catch (error) {
handleUploadError(error);
}
}
async function createUser(userData) {
const connection = await db.connect();
try {
await connection.beginTransaction();
const user = await connection.query(
'INSERT INTO users SET ?',
userData
);
await connection.query(
'INSERT INTO user_settings SET ?',
{ userId: user.insertId }
);
await connection.commit();
return user;
} catch (error) {
await connection.rollback();
throw error;
} finally {
connection.release();
}
}
async function loadApplication() {
// 并行加载资源
const [
config,
translations,
userPreferences
] = await Promise.all([
loadConfig(),
loadTranslations(),
loadUserPreferences()
]);
// 初始化应用
await initApp({ config, translations, userPreferences });
}
String.prototype.padStart()
/ String.prototype.padEnd()
详细讲解:
padStart()
:在字符串开头填充字符padEnd()
:在字符串末尾填充字符str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])
代码示例:
// 基础用法
'abc'.padStart(6); // ' abc'
'abc'.padStart(6, '0'); // '000abc'
'abc'.padEnd(6, '0'); // 'abc000'
// 截断填充字符
'abc'.padStart(6, '123456'); // '123abc'
// 实际应用
const numbers = [1, 2, 3, 4];
numbers.map(n => n.toString().padStart(2, '0')); // ['01', '02', '03', '04']
应用场景:
// 格式化日期
const month = '5';
const day = '7';
const formattedDate = `${month.padStart(2, '0')}/${day.padStart(2, '0')}`; // "05/07"
// 格式化数字
const formatNumber = n => n.toString().padStart(6, '0');
formatNumber(123); // "000123"
const data = ['a', 'ab', 'abc'];
const aligned = data.map(s => s.padEnd(5, ' '));
// ["a ", "ab ", "abc "]
// 信用卡号掩码
const maskCreditCard = num =>
num.slice(-4).padStart(num.length, '*');
maskCreditCard('1234567890123456'); // "************3456"
Object.getOwnPropertyDescriptors()
详细讲解:
Object.getOwnPropertyDescriptors(obj)
代码示例:
const obj = {
name: 'test',
get age() { return 18; }
};
const descriptors = Object.getOwnPropertyDescriptors(obj);
// {
// name: {
// value: 'test',
// writable: true,
// enumerable: true,
// configurable: true
// },
// age: {
// get: [Function: get age],
// set: undefined,
// enumerable: true,
// configurable: true
// }
// }
应用场景:
const source = {
set name(value) {
this._name = value;
},
get name() {
return this._name;
}
};
const clone = Object.defineProperties({},
Object.getOwnPropertyDescriptors(source)
);
const target = {
name: 'target'
};
const source = {
get value() {
return 42;
}
};
Object.defineProperties(target,
Object.getOwnPropertyDescriptors(source)
);
SharedArrayBuffer
Array.prototype.flat()
和 Array.prototype.flatMap()
详细讲解:
flat()
:将嵌套数组扁平化处理flatMap()
:先映射再扁平化,相当于 map()
和 flat()
的组合arr.flat([depth])
:depth 默认为 1arr.flatMap((currentValue, index, array) => { … })
flatMap
只能展开一层代码示例:
// flat() 基础用法
const numbers = [1, [2, 3], [4, [5, 6]]];
numbers.flat(); // [1, 2, 3, 4, [5, 6]]
numbers.flat(2); // [1, 2, 3, 4, 5, 6]
// 处理空项
const array = [1, 2, , 4, 5];
array.flat(); // [1, 2, 4, 5]
// flatMap() 示例
const sentences = ["Hello world", "JavaScript is awesome"];
sentences.flatMap(s => s.split(' '));
// ['Hello', 'world', 'JavaScript', 'is', 'awesome']
// 数值计算
const numbers = [1, 2, 3];
numbers.flatMap(x => [x, x * 2]);
// [1, 2, 2, 4, 3, 6]
应用场景:
// 处理多层JSON数据
const comments = [
{ replies: [
{ text: 'Great!', replies: [] },
{ text: 'Nice!', replies: [] }
]},
{ replies: [
{ text: 'Awesome!', replies: [] }
]}
];
const allReplies = comments
.flatMap(comment => comment.replies)
.map(reply => reply.text);
// 分词并过滤
const text = [" hello ", " world "];
const words = text
.flatMap(str => str.trim().split(/\s+/))
.filter(Boolean);
Object.fromEntries()
详细讲解:
Object.fromEntries(iterable)
Object.entries()
的逆操作代码示例:
// 基础用法
const entries = [
['name', 'Alice'],
['age', 25],
['city', 'Beijing']
];
const obj = Object.fromEntries(entries);
// { name: 'Alice', age: 25, city: 'Beijing' }
// Map 转对象
const map = new Map([
['foo', 'bar'],
['baz', 42]
]);
const obj2 = Object.fromEntries(map);
// { foo: 'bar', baz: 42 }
// URL 参数处理
const paramsString = 'user=alice&page=1&limit=10';
const searchParams = new URLSearchParams(paramsString);
const paramsObject = Object.fromEntries(searchParams);
// { user: 'alice', page: '1', limit: '10' }
应用场景:
// 过滤对象属性
const object = { a: 1, b: 2, c: 3 };
const filtered = Object.fromEntries(
Object.entries(object)
.filter(([key, value]) => value > 1)
);
// { b: 2, c: 3 }
// FormData 转对象
const form = document.querySelector('form');
const formData = new FormData(form);
const data = Object.fromEntries(formData);
// 合并默认配置
const defaults = { theme: 'light', lang: 'en' };
const userPrefs = new Map([
['theme', 'dark'],
['fontSize', '16px']
]);
const config = {
...defaults,
...Object.fromEntries(userPrefs)
};
String.prototype.trimStart()
/ String.prototype.trimEnd()
详细讲解:
trimStart()
:删除字符串开头的空白字符trimEnd()
:删除字符串末尾的空白字符trimLeft()
是 trimStart()
的别名trimRight()
是 trimEnd()
的别名代码示例:
const text = ' Hello World ';
text.trimStart(); // 'Hello World '
text.trimEnd(); // ' Hello World'
// 实际应用
function normalizeInput(input) {
return input.trimStart().toLowerCase();
}
// 处理多行文本
const multiline = `
Some text
with spaces
`;
multiline.trimStart().trimEnd(); // 'Some text\n with spaces'
详细讲解:
代码示例:
const sym1 = Symbol('foo');
console.log(sym1.description); // 'foo'
const sym2 = Symbol();
console.log(sym2.description); // undefined
// 实际应用
const symbols = {
RED: Symbol('red'),
GREEN: Symbol('green'),
BLUE: Symbol('blue')
};
function getColorName(colorSymbol) {
return colorSymbol.description || 'unknown';
}
详细讲解:
代码示例:
function /* comment */ test(x) {
return x + 1; // increment
}
console.log(test.toString());
// 'function /* comment */ test(x) {
// return x + 1; // increment
// }'
// 实际应用:函数文档生成
function extractFunctionDocs(fn) {
const source = fn.toString();
const comments = source.match(/\/\*[\s\S]*?\*\/|\/\/.*/g) || [];
return comments.map(c => c.trim());
}
详细讲解:
代码示例:
// 旧写法
try {
// 可能抛出错误的代码
} catch (error) {
// 不使用 error 对象
console.log('发生错误');
}
// 新写法
try {
// 可能抛出错误的代码
} catch {
console.log('发生错误');
}
// 实际应用
async function validateJSON(str) {
try {
JSON.parse(str);
return true;
} catch {
return false;
}
}
Promise.allSettled()
详细讲解:
Promise.allSettled(iterable)
status
:‘fulfilled’ 或 ‘rejected’value
:成功值(如果成功)reason
:失败原因(如果失败)代码示例:
const promises = [
fetch('/api/user'),
fetch('/api/invalid-url'),
fetch('/api/posts')
];
const results = await Promise.allSettled(promises);
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log('成功:', result.value);
} else {
console.log('失败:', result.reason);
}
});
// 实际应用
async function uploadFiles(files) {
const uploadPromises = files.map(file => uploadFile(file));
const results = await Promise.allSettled(uploadPromises);
const succeeded = results.filter(r => r.status === 'fulfilled');
const failed = results.filter(r => r.status === 'rejected');
return {
successful: succeeded.length,
failed: failed.length,
failedFiles: failed.map(r => r.reason)
};
}
?.
和空值合并运算符 ??
详细讲解:
?.
:
??
:
||
:不会将 falsy 值(如 0、‘’)视为假代码示例:
// 可选链示例
const user = {
address: {
street: 'Main St',
city: 'Beijing'
},
orders: [
{ id: 1, items: ['book', 'pen'] }
]
};
// 属性访问
console.log(user?.address?.street); // 'Main St'
console.log(user?.contact?.phone); // undefined(不报错)
// 方法调用
console.log(user.getAge?.()); // undefined(不报错)
// 数组访问
console.log(user.orders?.[0]?.items); // ['book', 'pen']
// 空值合并示例
const config = {
timeout: 0,
retries: null,
maxSize: undefined
};
console.log(config.timeout ?? 1000); // 0(保留0值)
console.log(config.retries ?? 3); // 3
console.log(config.maxSize ?? 5000); // 5000
应用场景:
async function getUserData(userId) {
const response = await fetch(`/api/users/${userId}`);
const user = await response.json();
return {
name: user?.name ?? 'Unknown',
email: user?.contact?.email ?? 'No email',
city: user?.address?.city ?? 'No city',
orders: user?.orders?.length ?? 0
};
}
function initializeApp(config) {
return {
debug: config?.debug ?? false,
api: {
url: config?.api?.url ?? 'http://localhost',
timeout: config?.api?.timeout ?? 5000,
retries: config?.api?.retries ?? 3
},
theme: config?.theme ?? 'light'
};
}
详细讲解:
n
或使用 BigInt()
代码示例:
// 创建 BigInt
const bigInt = 9007199254740991n;
const anotherBigInt = BigInt("9007199254740991");
// 基本运算
const sum = bigInt + 1n;
const product = bigInt * 2n;
// 比较操作
console.log(1n < 2n); // true
console.log(2n > 1n); // true
console.log(2n === 2); // false
console.log(2n == 2); // true
// 实际应用
function factorial(n) {
let result = 1n;
for (let i = 2n; i <= n; i++) {
result *= i;
}
return result;
}
console.log(factorial(50n)); // 超大整数阶乘
详细讲解:
代码示例:
// 以前的兼容性写法
const getGlobal = function() {
if (typeof self !== 'undefined') return self;
if (typeof window !== 'undefined') return window;
if (typeof global !== 'undefined') return global;
throw new Error('无法找到全局对象');
};
// 现在可以直接使用
console.log(globalThis); // 指向当前环境的全局对象
// 实际应用
function isRunningInBrowser() {
return globalThis.window === globalThis;
}
function isRunningInNode() {
return globalThis.process?.versions?.node != null;
}
详细讲解:
import()
代码示例:
// 基础用法
const modulePath = './modules/math.js';
import(modulePath)
.then(module => {
console.log(module.sum(2, 3));
});
// 异步函数中使用
async function loadModule(name) {
const module = await import(`./modules/${name}.js`);
return module;
}
// 条件导入
async function loadLocaleMessages(locale) {
const messages = await import(
`/i18n/${locale}.js`
);
return messages.default;
}
// 实际应用:按需加载组件
async function loadComponent(name) {
const component = await import(
`/components/${name}.js`
);
return component.default;
}
String.prototype.replaceAll()
详细讲解:
str.replaceAll(searchValue, replacement)
searchValue
:要替换的字符串或正则表达式replacement
:替换值(字符串或函数)代码示例:
// 基础用法
const str = 'hello hello world';
str.replaceAll('hello', 'hi'); // 'hi hi world'
// 使用正则表达式
const text = 'cat, bat, sat, fat';
text.replaceAll(/[a-z]at/g, 'word'); // 'word, word, word, word'
// 使用替换函数
const prices = '价格: $10, $20, $30';
prices.replaceAll(/\$(\d+)/g, (match, p1) => `¥${p1 * 7}`);
// '价格: ¥70, ¥140, ¥210'
Promise.any()
详细讲解:
Promise.any(iterable)
代码示例:
// 基础用法
const promises = [
fetch('https://api1.example.com'),
fetch('https://api2.example.com'),
fetch('https://api3.example.com')
];
try {
const firstSuccess = await Promise.any(promises);
console.log('第一个成功的响应:', firstSuccess);
} catch (error) {
console.log('所有请求都失败了:', error.errors);
}
// 实际应用:图片加载
async function loadImage(urls) {
try {
const firstImage = await Promise.any(
urls.map(url => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
});
})
);
return firstImage;
} catch {
throw new Error('所有图片加载失败');
}
}
详细讲解:
代码示例:
class Counter {
// 公共字段
count = 0;
// 私有字段
#privateValue = 42;
// 静态字段
static instances = 0;
// 私有静态字段
static #lastCreated;
constructor() {
Counter.instances++;
Counter.#lastCreated = new Date();
}
increment() {
this.count++;
this.#privateValue++;
}
static getLastCreated() {
return Counter.#lastCreated;
}
}
详细讲解:
代码示例:
// config.js
export const config = await fetch('/api/config').then(r => r.json());
// 动态导入
const strings = await import(`/i18n/${navigator.language}`);
// 条件加载模块
const moduleA = await import(
condition ? './moduleA.js' : './moduleB.js'
);
findLast
和 findLastIndex
详细讲解:
arr.findLast(callback)
arr.findLastIndex(callback)
代码示例:
const numbers = [1, 3, 5, 7, 3, 9];
// 查找最后一个小于 5 的数
numbers.findLast(n => n < 5); // 3
// 查找最后一个小于 5 的数的索引
numbers.findLastIndex(n => n < 5); // 4
// 实际应用
const transactions = [
{ id: 1, status: 'pending' },
{ id: 2, status: 'completed' },
{ id: 3, status: 'pending' },
{ id: 4, status: 'completed' }
];
// 查找最后一个待处理的交易
const lastPending = transactions.findLast(
t => t.status === 'pending'
);
Promise.withResolvers()
详细讲解:
Promise.withResolvers()
promise
、resolve
和 reject
的对象代码示例:
// 传统方式
let resolvePromise, rejectPromise;
const promise = new Promise((resolve, reject) => {
resolvePromise = resolve;
rejectPromise = reject;
});
// 使用 withResolvers
const { promise, resolve, reject } = Promise.withResolvers();
// 实际应用
class Deferred {
constructor() {
const { promise, resolve, reject } = Promise.withResolvers();
this.promise = promise;
this.resolve = resolve;
this.reject = reject;
}
}
详细讲解:
v
标志代码示例:
// Unicode 属性类
const regex1 = /[\p{Letter}\p{Number}]/v;
// 集合操作
const regex2 = /[\p{Letter}--\p{Script=Greek}]/v; // 字母但不是希腊字母
const regex3 = /[\p{Letter}&&\p{Script=Latin}]/v; // 拉丁字母
// 实际应用
function isValidIdentifier(str) {
return /^[\p{Letter}_$][\p{Letter}\p{Number}_$]*$/v.test(str);
}
ArrayBuffer.prototype.transfer()
详细讲解:
arrayBuffer.transfer()
代码示例:
// 基础用法
const buffer1 = new ArrayBuffer(1024);
const buffer2 = buffer1.transfer();
// buffer1 现在已分离,不能再使用
// buffer2 包含原始数据
// 实际应用:数据传输
async function processLargeData(data) {
const buffer = new ArrayBuffer(data.length);
new Uint8Array(buffer).set(data);
await worker.postMessage(buffer.transfer(), [buffer]);
}
Atomics.waitAsync()
详细讲解:
Atomics.waitAsync(typedArray, index, value[, timeout])
代码示例:
s
// 基础用法
const shared = new SharedArrayBuffer(4);
const int32 = new Int32Array(shared);
async function waitForChange() {
const result = await Atosmics.waitAsync(int32, 0, 0).value;
console.log('值已更改:', result);
}
// 实际应用:线程同步
class AsyncLock {
#shared = new SharedArrayBuffer(4);
#int32 = new Int32Array(this.#shared);
async acquire(timeout = Infinity) {
while (true) {
if (Atomics.compareExchange(this.#int32, 0, 0, 1) === 0) {
return true;
}
await Atomics.waitAsync(this.#int32, 0, 1, timeout).value;
}
}
release() {
Atomics.store(this.#int32, 0, 0);
Atomics.notify(this.#int32, 0, 1);
}
}
Promise.withResolvers()
详细讲解:
Promise.withResolvers()
promise
、resolve
和 reject
的对象代码示例:
// 传统方式
let resolvePromise, rejectPromise;
const promise = new Promise((resolve, reject) => {
resolvePromise = resolve;
rejectPromise = reject;
});
// 使用 withResolvers
const { promise, resolve, reject } = Promise.withResolvers();
// 实际应用:延迟执行
class Deferred {
constructor() {
const { promise, resolve, reject } = Promise.withResolvers();
this.promise = promise;
this.resolve = resolve;
this.reject = reject;
}
}
详细讲解:
Object.groupBy()
:按条件对数组元素进行分组Map.groupBy()
:类似 Object.groupBy,但返回 Map代码示例:
const inventory = [
{ name: "苹果", type: "水果", quantity: 5 },
{ name: "香蕉", type: "水果", quantity: 3 },
{ name: "胡萝卜", type: "蔬菜", quantity: 8 }
];
// 使用 Object.groupBy
const groupedByType = Object.groupBy(inventory, item => item.type);
// {
// 水果: [
// { name: "苹果", type: "水果", quantity: 5 },
// { name: "香蕉", type: "水果", quantity: 3 }
// ],
// 蔬菜: [
// { name: "胡萝卜", type: "蔬菜", quantity: 8 }
// ]
// }
// 使用 Map.groupBy
const groupedByQuantity = Map.groupBy(inventory,
item => item.quantity > 5 ? '库存充足' : '库存不足'
);
详细讲解:
WeakMap.prototype.delete()
代码示例:
// 缓存管理
const cache = new WeakMap();
class ResourceManager {
constructor() {
this.resources = new WeakMap();
}
getResource(key) {
if (!this.resources.has(key)) {
const resource = loadResource(key);
this.resources.set(key, resource);
}
return this.resources.get(key);
}
releaseResource(key) {
if (this.resources.delete(key)) {
console.log('资源已释放');
}
}
}
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error('获取用户数据失败', {
cause: {
code: response.status,
url: response.url
}
});
}
return await response.json();
} catch (error) {
throw new Error('用户数据处理失败', { cause: error });
}
}
try {
await fetchUserData(123);
} catch (error) {
console.error('错误:', error.message);
console.error('原因:', error.cause);
}
详细讲解:
@
符号代码示例:
// 类装饰器
function logged(target) {
return class extends target {
constructor(...args) {
console.log('Creating instance...');
super(...args);
}
};
}
// 方法装饰器
function measure(target, key, descriptor) {
const original = descriptor.value;
descriptor.value = async function(...args) {
const start = performance.now();
const result = await original.apply(this, args);
const end = performance.now();
console.log(`${key} took ${end - start}ms`);
return result;
};
return descriptor;
}
@logged
class Example {
@measure
async fetchData() {
// ... 异步操作
}
}
详细讲解:
#{}
#[]
代码示例:
// Record 示例
const point = #{ x: 10, y: 20 };
// point.x = 30; // 错误:不可修改
// Tuple 示例
const coords = #[1, 2, 3];
// coords[0] = 4; // 错误:不可修改
// 结构相等性
#{ x: 1, y: 2 } === #{ x: 1, y: 2 }; // true
#[1, 2, 3] === #[1, 2, 3]; // true
// 作为 Map 键
const map = new Map();
map.set(#{ id: 1 }, 'value');
详细讲解:
|>
代码示例:
// 基础用法
const double = n => n * 2;
const increment = n => n + 1;
const square = n => n ** 2;
// 传统写法
square(increment(double(5))); // 121
// 管道操作符
5 |> double
|> increment
|> square; // 121
// 异步操作
async function processData(data) {
return data
|> await validate
|> await transform
|> await save;
}
详细讲解:
match
表达式代码示例:
// 基础匹配
const result = match (response) {
when { status: 200, data } -> handleSuccess(data),
when { status: 404 } -> handleNotFound(),
when { status } if status >= 500 -> handleServerError(),
default -> handleUnknown()
};
// 数组匹配
const parse = match (tokens) {
when [] -> null,
when [{ type: 'number', value }] -> Number(value),
when [{ type: 'string', value }] -> String(value),
default -> throw new SyntaxError()
};
特性选择建议
工具链配置
// babel.config.js 示例
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
browsers: ['> 1%', 'last 2 versions']
},
useBuiltIns: 'usage',
corejs: 3
}]
]
};
性能优化提示
调试技巧
--harmony
标志测试新特性学习资源