【编程指南】ES2016到ES2023新特性解析一网打尽

ES2016

Array.prototype.includes()

Array.prototype.includes 方法: 这个方法用于检查数组是否包含特定元素,如果包含则返回 true,否则返回 false

ini 复制代码
// 我有一个水果篮子
const fruitBasket = ['apple', 'banana', 'orange', 'grape'];

// 我要检查篮子里是否有橙子
const hasOrange = fruitBasket.includes('orange');
console.log(hasOrange); // 输出: true

// 我还想知道篮子里是否有葡萄
const hasGrape = fruitBasket.includes('grape');
console.log(hasGrape); // 输出: true

// 现在我要检查篮子里是否有西瓜
const hasWatermelon = fruitBasket.includes('watermelon');
console.log(hasWatermelon); // 输出: false

求幂运算符

求幂运算符: 这是一个新的算术运算符,用于计算一个数的幂

arduino 复制代码
// 我要计算 2 的 3 次幂
const result = 2 ** 3;
console.log(result); // 输出: 8

ES2017

Object.values/Object.entries

Object.valuesObject.entries 方法:

  • Object.values:把字典里的值都拿出来,就像拿出一个个水果。
  • Object.entries:把字典里的值和对应的名字都拿出来,就像知道每个水果的名字和样子。
css 复制代码
const person = {
  name: 'Alice',
  age: 25,
  city: 'New York'
};

const values = Object.values(person); // 得到:['Alice', 25, 'New York']
const entries = Object.entries(person); // 得到:[['name', 'Alice'], ['age', 25], ['city', 'New York']]

字符串补全

字符串补全是一种操作,可以在一个字符串的末尾添加一些额外的字符,使得字符串的长度达到特定的目标长度。

arduino 复制代码
console.log('a'.padStart(5, '1')); // 1111a
console.log('a'.padEnd(5, '2')); // a2222

async/await

async/await 是 JavaScript 中处理异步操作的一种方式,它使得在代码中处理异步任务更加直观和易读。

javascript 复制代码
function simulateFetchingData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Data fetched');
    }, 1000);
  });
}

async function fetchData() {
  console.log('Fetching data...');
  const data = await simulateFetchingData();
  console.log(data); // 输出: 'Data fetched'
}

fetchData(); // 会在一秒后输出: 'Data fetched'

Object.getOwnPropertyDescriptors()

用于获取一个对象的所有属性的详细信息,包括属性的特性(例如可写、可枚举、可配置)以及属性的值。

ini 复制代码
const item = {
  name: 'Widget',
  color: 'Blue'
};

const descriptors = Object.getOwnPropertyDescriptors(item);
console.log(descriptors);

参数列表支持尾逗号

函数参数列表最后一个参数后面允许有一个逗号,这在以后添加更多参数时更方便。

javascript 复制代码
function inviteFriends(friend1, friend2, friend3,) {
  console.log("Inviting:", friend1, friend2, friend3);
}

inviteFriends('Alice', 'Bob', 'Charlie',); // 输出: Inviting: Alice Bob Charlie

ES2018

for-await-of 异步迭代

异步迭代在 Node.js 中用的会多些,使用 for-await-of 遍历异步数据。例如使用 MongoDB 查询数据返回值默认为一个游标对象,避免了一次性把数据读入应用内存

想象你有一组需要分步完成的任务,比如读取多个文件,这些任务都是异步的。for-await-of 就像是一个一个完成这些任务,等一个任务完成后再进行下一个。

javascript 复制代码
async function fetchUserData(userId) {
  // 模拟异步操作,比如从服务器获取用户数据
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`User data for ID ${userId}`);
    }, 1000);
  });
}

const userIds = [1, 2, 3];

(async () => {
  for await (const userData of userIds.map(fetchUserData)) {
    console.log(userData);
  }
})();

Promise.finally

Promise.finally 是在 Promise 结束(不管是成功还是失败)后,无论如何都会执行的代码块。

typescript 复制代码
const fetchData = new Promise((resolve, reject) => {
  // 模拟异步操作
  setTimeout(() => {
    resolve('Data fetched');
  }, 1000);
});

fetchData
  .then(data => console.log(data))
  .catch(error => console.error(error))
  .finally(() => console.log('Promise finished'));

新的正则表达式功能

  • 正则命名组捕获
  • 正则表达式 Unicode 转义
  • 正则表达式dotAll模式
  • 正则 Lookbehind 断言

Rest/Spread 属性

这些属性让你可以更方便地处理函数参数和对象数组的拷贝。

想象你要组织一场聚会,需要把朋友们的名字一个一个列出来。Rest 属性就像是把这些名字都捡起来放进一个列表,而 Spread 属性就像是把这个列表里的名字一个一个散落出来。

javascript 复制代码
// Rest 属性
function inviteFriends(host, ...guests) {
  console.log(`${host}邀请了${guests.join(', ')}参加聚会`);
}

inviteFriends('Alice', 'Bob', 'Charlie', 'David');

// Spread 属性
const oldFriends = ['John', 'Jane'];
const newFriends = ['Mike', 'Emily'];
const allFriends = [...oldFriends, ...newFriends];

console.log(allFriends); // 输出: ['John', 'Jane', 'Mike', 'Emily']

解除模版字符串限制

解析器会去查找有效的转义序列,例如 Unicode​ 字符以 "\u"​ 开头,例如 \u00A9​,以下 "\unicode"​ 是一个非法的 Unicode​ 字符,在之前就会得到一个 SyntaxError: malformed Unicode character escape sequence​ 错误。ES2018 中解除了这个限制,当遇到不合法的字符时也会正常执行,得到的是一个 undefined​,通过 raw 属性还是可以取到原始字符串。

javascript 复制代码
function latex(strings, ...exps) {
  console.log(strings); // [ undefined ]
  console.log(strings.raw);  // [ 'latex \unicode' ]
 }
 
 latex`latex \unicode`;

ES2019

可选的 catch 参数

允许在 catch 块中省略异常参数,使得在不需要异常信息时代码更简洁。

arduino 复制代码
try {
  // 一些可能会发生问题的代码
} catch {
  // 不需要异常参数
  console.log('出错了');
}

Symbol.prototype.description

这是一个新的方法,用于返回 Symbol 的可读描述,方便开发者理解 Symbol 的用途。

想象你有很多特殊的印章,每个印章代表不同的事情。description 就像是告诉你每个印章代表的是什么,让你能更好地理解这些印章。

ini 复制代码
const mySymbol = Symbol('这是一个特殊的标记');
console.log(mySymbol.description); // 输出: '这是一个特殊的标记'

函数的 toString() 方法

一个函数对象的方法,用于将函数的源代码转化成字符串。

javascript 复制代码
function sayHello() {
  console.log('Hello!');
}

const functionString = sayHello.toString();
console.log(functionString); // 输出函数的源代码字符串

Object.fromEntries()

一个用于将键值对列表转换成对象的方法。

想象你有一些标签和对应的价值,现在你想把它们整理成一个清单。Object.fromEntries() 就像是帮你把这些标签和价值整理成一个清单。

ini 复制代码
const entries = [
  ['name', 'Alice'],
  ['age', 30]
];

const person = Object.fromEntries(entries);
console.log(person); // 输出: { name: 'Alice', age: 30 }

消除前后空格

一种字符串处理方法,用于去除字符串开头和结尾的空格。

ini 复制代码
const messyText = '   这里有很多空格   ';
const cleanText = messyText.trim();
console.log(cleanText); // 输出: '这里有很多空格'

数组 flat()、flatMap()

数组的两个方法,用于将多维数组拉平为一维数组,以及在拉平的同时对数组元素进行操作。Infinity是flat对数组深度展开,flatMap则只能展开一层。

想象你有一些叠在一起的盒子,里面还有更小的盒子。flat() 就像是把所有的盒子都打开,把里面的东西拿出来放在一起。而 flatMap() 就像是在拿出东西的同时,还可以对它们做些处理。

ini 复制代码
const nestedArray = [1, [2, [3, [4]]]];

const flattenedArray = nestedArray.flat();
console.log(flattenedArray); // 输出: [1, 2, [3, [4]]]

const flattened = nestedArray.flat(Infinity);
console.log(flattenedArray); // 输出: [1, 2, 3, 4]

const doubledArray = nestedArray.flatMap(value => value * 2);
console.log(doubledArray); // 输出: [2, 4, 6, [4]]

JSON 超集

ES2019 之前 JSON 字符串中不支持 \u2028(行分隔符)、\u2029(段落分隔符) 字符,否则 JSON.parse() 会报错,现在给予了支持。

ini 复制代码
const json = '"\u2028"';
JSON.parse(json);

JSON.stringify() 加强格式转化

防止 JSON.stringify 返回格式错误的 Unicode 字符串

ES2020

matchAll 匹配所有

字符串的新方法,可以通过正则表达式来查找字符串中的所有匹配项。

想象你有一篇文章,想找出所有包含某个特定单词的地方。matchAll 就像是帮你在文章中找到所有这样的地方

ini 复制代码
const text = 'Hello world, hello universe';
const regex = /hello/gi;

for (const match of text.matchAll(regex)) {
  console.log(match);
}

模块新特性

  • import 动态导入 动态导入意思是当你需要该模块时才会进行加载,返回的是一个 Promise 对象。只有在 ES Modules 模块规范下才支持。
javascript 复制代码
// index-a.mjs
export default {
  hello () {
    console.log(`hello JavaScript`);
  }
}

// index-b.mjs
import('./index-a.mjs').then(module {
  module.default.hello(); // hello JavaScript
})
  • import.meta import.meta 指当前模块的元数据。一个广泛支持的属性是 import.meta.url,以字符串形式输出当前模块的文件路径。

Bigint

BigInt 是一种新的数据类型,用于表示大整数,超出了 JavaScript 中常见的数值范围。

想象你要表示一个非常大的数字,比如宇宙的年龄。BigInt 就像是一个特别大的数字框,可以容纳更多的数字。

ini 复制代码
const bigNumber = 1234567890123456789012345678901234567890n;
console.log(bigNumber);

Promise.allSettled

这是 Promise 的一个新方法,可以等待多个 Promise 都完成(无论成功还是失败)后再继续。

ini 复制代码
const promises = [
  Promise.resolve('Success!'),
  Promise.reject('Error!')
];

Promise.allSettled(promises)
  .then(results => console.log(results));

全局对象

JavaScript 可以运行在不同的环境,浏览器为 window、Node.js 为 global。为了能够统一全局环境变量,引入了 globalThis。

ini 复制代码
window === globalThis // 浏览器环境
global === globalThis // Node.js 环境

for-in 机制

这是对 for-in 循环的更新,用于更好地遍历对象的可枚举属性。 想象你要看一个箱子里有什么东西,但有些东西可能隐藏得很深。for-in 机制就像是帮你把箱子里所有东西都拿出来看一遍。

ini 复制代码
const obj = { a: 1, b: 2, c: 3 };

for (const key in obj) {
  console.log(key, obj[key]);
}

可选链

这是一个新的语法,用于在访问对象的属性时,避免因为属性不存在而导致错误。

ini 复制代码
const person = {
  name: 'Alice',
  contact: {
    phone: '123-456-7890'
  }
};

const phoneNumber = person?.contact?.phone;
console.log(phoneNumber); // 输出: '123-456-7890'

空值合并

这是一种新的语法,用于给变量赋值时,如果变量的值为 nullundefined,就使用默认值。

想象你要吃冰淇淋,但是不知道哪种口味有,所以你要确保有一种口味可以选。空值合并就像是在选择口味时,如果没有你喜欢的,就选择默认的口味。

ini 复制代码
const favoriteIceCream = null;
const iceCreamChoice = favoriteIceCream ?? 'Vanilla';
console.log(iceCreamChoice); // 输出: 'Vanilla'

ES2021

String.prototype.replaceAll

字符串的一个新方法,用于替换所有匹配的子字符串。

想象你在纸上写了一句话,但是有一些词你想换成其他词。replaceAll 就像是帮你把所有要换的词都换掉。

ini 复制代码
const originalText = 'Hello world, hello universe';
const newText = originalText.replaceAll('hello', 'hi');
console.log(newText); // 输出: 'Hi world, hi universe'

Promise.any

Promise.anyPromise 的一个新方法,用于在一组 Promise 中,只要有一个成功就返回,不必等待所有 Promise 都结束。

typescript 复制代码
const promises = [
  Promise.reject('Error 1'),
  Promise.resolve('Success!'),
  Promise.reject('Error 2')
];

Promise.any(promises)
  .then(result => console.log(result))
  .catch(errors => console.error(errors));

数字分隔符

分隔符是一种在数字中插入下划线,以便更易读的语法。

ini 复制代码
const largeNumber = 1_000_000;
console.log(largeNumber); // 输出: 1000000

逻辑赋值运算符

结合了逻辑运算符 &&、||、??​ 和逻辑表达式 =。

css 复制代码
// "Or Or Equals" (or, the Mallet operator :wink:)
a ||= b; // a || (a = b);

// "And And Equals"
a &&= b; // a && (a = b);

// "QQ Equals"
a ??= b; // a ?? (a = b);

WeakRefs

WeakRefs 是一种新的对象引用类型,用于创建对对象的弱引用,不会影响对象的垃圾回收。

想象你有一个备忘录,但是只在你需要的时候才能看到。WeakRefs 就像是对对象的一种轻量级引用,不会让对象被保持得太久。

ini 复制代码
const obj = { data: 'Some data' };
const weakRef = new WeakRef(obj);

// 只有当 obj 还存在时,weakRef 才能获取到它
const retrievedObj = weakRef.deref();
console.log(retrievedObj?.data); // 输出: 'Some data'

ES2022

类私有属性

这是 JavaScript 中类的一个新特性,允许在类内部声明私有属性,仅在类的内部可访问。

想象你有一本笔记本,里面有些笔记是只有你能看到的。类私有属性就像是在类里面写下一些只有类自己能看到的东西。

javascript 复制代码
class Person {
  #name = 'Alice'; // 私有属性

  sayHello() {
    console.log(`Hello, my name is ${this.#name}`);
  }
}

const person = new Person();
person.sayHello(); // 输出: 'Hello, my name is Alice'
console.log(person.#name); // 无法访问私有属性

私有字段检查

一种新的访问控制,允许类的私有属性在外部被访问时触发特定的操作。

想象你的门上装有警报,如果有人试图进入你的房间,会发出声音。私有字段检查就像是在访问私有属性时触发警报。

arduino 复制代码
class BankAccount {
  #balance = 1000; // 私有属性

  #checkAccess() {
    console.log('Access to balance checked');
  }

  get balance() {
    this.#checkAccess();
    return this.#balance;
  }
}

const account = new BankAccount();
console.log(account.balance); // 输出: 'Access to balance checked' 和账户余额

顶层 await

允许在模块顶层使用 await

想象你在工作,需要等一份文件完成才能继续。顶层 await 就像是你在等这份文件,但不需要停下其他的工作。

ini 复制代码
// 在模块顶层使用 await
const data = await fetchData();
console.log(data);

.at 方法返回指定索引的元素

想象你有一个大盒子,里面有很多东西。.at 方法就像是帮你从盒子中取出特定位置的东西。

arduino 复制代码
const arr = [1, 2, 3, 4, 5];
console.log(arr.at(2)); // 输出: 3

const text = 'Hello';
console.log(text.at(1)); // 输出: 'e'

Object.hasOwn()

一个全局函数,用于检查对象是否具有指定的自有属性。

想象你有一张名单,上面写着一些名字。Object.hasOwn() 就像是帮你查看名单上是否有某个名字。

javascript 复制代码
const person = { name: 'Alice' };
console.log(Object.hasOwn(person, 'name')); // 输出: true
console.log(Object.hasOwn(person, 'age')); // 输出: false

异常链

一种更好地处理异常信息的方式,允许你在异常中包含更多信息。

想象你有一串蛋糕,但其中一个蛋糕有问题。异常链就像是在蛋糕上贴上标签,告诉你哪个蛋糕有问题,以及为什么有问题。

vbnet 复制代码
try {
  // 一些可能出错的代码
} catch (error) {
  const detailedError = new Error('详细错误信息');
  detailedError.originalError = error;
  throw detailedError;
}

类静态块

类的一个新特性,允许在类内部定义一块在类被初始化时执行的代码。

想象你在搭建一个房子,房子刚建好时,你想做一些特定的准备工作。类静态块就像是在房子刚建好时,执行一些初始化工作。

javascript 复制代码
class MyClass {
  static {
    console.log('类初始化中...');
  }

  constructor() {
    console.log('实例化对象');
  }
}

const obj = new MyClass();

ES2023

Array 支持从尾部查找

新增两个方法: .findLast()、.findLastIndex()​ 从数组的最后一个元素开始查找,可以同 find()、findIndex() 做一个对比。

想象你有一条长长的队伍,人们站成一列。你可以从前面开始数,也可以从后面开始数。数组支持从尾部查找就像是你从队伍尾部开始数人。

ini 复制代码
const arr = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }];

// find vs findLast
console.log(arr.find(n n.value % 2 === 1)); // { value: 1 }
console.log(arr.findLast(n n.value % 2 === 1)); // { value: 3 }

// findIndex vs findLastIndex
console.log(arr.findIndex(n n.value % 2 === 1)); // 0
console.log(arr.findLastIndex(n n.value % 2 === 1)); // 2

Hashbang 语法

Hashbang 语法是一种在 URL 中使用 #! 符号,用于标记 Web 应用中的前端路由。

想象你有一本书,但书中有很多章节。你可以用不同的书签快速翻到你想读的章节。Hashbang 语法就像是在 URL 中放了一个特殊的书签,让你能迅速定位到网页的某个部分。

ruby 复制代码
// URL 中的 Hashbang
https://example.com/#!/page1
https://example.com/#!/page2
相关推荐
be or not to be13 小时前
HTML入门系列:从图片到表单,再到音视频的完整实践
前端·html·音视频
90后的晨仔14 小时前
在macOS上无缝整合:为Claude Code配置魔搭社区免费API完全指南
前端
沿着路走到底15 小时前
JS事件循环
java·前端·javascript
子春一215 小时前
Flutter 2025 可访问性(Accessibility)工程体系:从合规达标到包容设计,打造人人可用的数字产品
前端·javascript·flutter
白兰地空瓶15 小时前
别再只会调 API 了!LangChain.js 才是前端 AI 工程化的真正起点
前端·langchain
jlspcsdn16 小时前
20251222项目练习
前端·javascript·html
行走的陀螺仪16 小时前
Sass 详细指南
前端·css·rust·sass
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ16 小时前
React 怎么区分导入的是组件还是函数,或者是对象
前端·react.js·前端框架
LYFlied17 小时前
【每日算法】LeetCode 136. 只出现一次的数字
前端·算法·leetcode·面试·职场和发展
子春一217 小时前
Flutter 2025 国际化与本地化工程体系:从多语言支持到文化适配,打造真正全球化的应用
前端·flutter