跳到主要内容

ECMAScript Version

VersionOfficial NameDateDescription
JavaScript 1.01995by Brendan Eich
ES1ECMAScript 11997ECMA-262
ES2ECMAScript 21998
ES3ECMAScript 31999
ES4ECMAScript 4未发布
ES5ECMAScript 52009
ES6ECMAScript 20152015
ECMAScript 20162016
ECMAScript 20172017
ECMAScript 20182018
ECMAScript 20192019
ECMAScript 20202020
ECMAScript 20212021
ECMAScript 20222022
ECMAScript 20232023
ECMAScript 20242024
ES.Next下一个版本
ESNodeJS
ES2022NodeJS 20
ES2022NodeJS 18
ES2021NodeJS 16
ES2020NodeJS 14
ES2019NodeJS 12
ES2018NodeJS 10
ES2017NodeJS 8.10
提示
  • 今年采纳的建议,发布到下一年版本,因此会相差一年版本号
stagefornote
stage 0Strawperson
stage 1Proposal
stage 2Draft描述准确
stage 3Candidate实现,等待用户使用反馈
stage 4Finished准备添加到 标准
proposalstagenote
decoratorsstage 3TS 5.0
decorator-metadatastage 3TS 5.2
Import AttributesTS 5.3
temporalstage 3
shadowrealmstage 3
binary-ast
set-methodsstage 3
record-tuplestage 2
async-contextstage 2
👀
syntaxChromeNameNote
?.Chrome80Optional chaining
??Chrome80Nullish coalescing operator
??=Chrome85Nullish coalescing assignment
#nameChrome74Private class fields
usingExplicit Resource ManagementTS 5.2
featVersionnote
globalThisChrome71, NodeJS12

Next

const date = Temporal.PlainDate(2024, 5, 1);
const time = new Temporal.PlainTime(10, 30);
const md = new Temporal.PlainMonthDay(5, 1);
const ym = new Temporal.PlainYearMonth(2024, 5);

ECMAScript 2024

  • Promise.withResolvers
  • Object.groupBy
  • Map.groupBy
  • RegExp /v, unicodeSets
    • /^\p{RGI_Emoji}$/v.test('😵‍💫')=true - Unicode string properties
    • /^[\q{😵‍💫}]$/v.test('😵‍💫')=true - \q for String literals
    • /^[\p{RGI_Emoji}--\q{😵‍💫}]$/v.test('😵‍💫')=false - 支持排除
  • ArrayBuffer.{resize,transfer}
    • SharedArrayBuffers 只能 grow, 且没有 transfer, 因为不支持 transfer
  • String.{isWellFormed,toWellFormed}
  • Atomics.waitAsync for SharedArrayBuffer

ECMAScript 2023

  • Array toReversed, toSorted, toSpliced, findLast, findLastIndex, with
    • TypedArray, Array
  • Hashbang Grammar - JS 直接作为可执行脚本
#!/usr/bin/env node
[1, 2].with(1, 0);

ECMAScript 2022

  • String at
  • Array at
  • Regex /d - start and end of the match
  • Object.hasOwn
  • Error cause
  • Top-level await
  • Class
    • field 定义
    • private field
    • static block
// Class Fields
class Counter extends HTMLElement {
// 私有
#val = 0;

get #x() { return #val; }
set #x(value) {
this.#val = value;
}

#inc() {
this.#val ++
}

// 静态
static #blue = "#0000ff";
static getBlue() {
return this.#blue
}
}

// regex 索引
// d -> indices
/a+(?<Z>z)?/d.exec('xaaaz').indices

// Top-level await
await Promise.resolve()

// static block
class C {
static {
// statements
}
}

// error cause
try {
throw new Error('error', { cause: err });
} catch (e) {
console.log('Caused by', e.cause);
}

// Array#at
[,-1].at(-1)

ECMAScript 2021

  • Promise.any
  • String#replaceAll
  • 数字分隔符 - 1_2_3_4
  • FinalizationRegistry
    • 注册 GC 回调
String.prototype.replaceAll;

Promise.any;

// WeakRef.prototype.deref
new WeakRef(() => 1);

// Logical Assignment Operators
a ||= b;
a &&= b;
a ??= b;

// Numeric separators
1_000_000_000;

ECMAScript 2020

  • BigInt
  • String matchAll()
  • ?? Nullish Coalescing Operator
  • ?. Optional Chaining Operator
  • &&= Logical AND Assignment Operator
  • ||= Logical OR Assignment
  • ??= Nullish Coalescing Assignment
  • Promise.allSettled
  • import() Dynamic Import
  • for-in 顺序
// String.prototype.matchAll
// 要求 RegEx 必须有 g 标识
'aa'.matchAll(/a/g);

// 动态 import
import('./foo.js');

// 模块元信息
import.meta;

BigInt;

// Promise.all 会在第一个异常时终止
Promise.allSettled;

globalThis;

// Optional Chaining
undefined?.b;

// Nullish coalescing Operator
undefined ?? null ?? 0 ?? 1;

ECMAScript 2019

  • String trimStart,trimEnd
  • Object fromEntries
  • Optional catch binding
  • Array flat, flatMap
  • Array.sort - 修改为稳定排序
  • JSON superset
    • U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR
  • Function.prototype.toString revision
    • 修改 Function.toString 返回完整无修改源码
  • Well-formed JSON.stringify
    • 修复 JSON.stringify 处理 \u 的问题
    • 避免返回错误 Unicode escape
// Optional catch binding
try {
} catch {}

Symbol.prototype.description;

Object.fromEntries([['k', 'v']]);

// String.prototype.{trimStart,trimEnd}
' 1 '.trimStart().trimEnd();

String.prototype.matchAll;

// Array.prototype.{flat,flatMap}
[[1], [2]].flat();
[0, 0].flatMap((_, i) => [1]);

ECMAScript 2018

// Regex Named Group
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u.exec('2015-01-02')
// Regex s -> dot all, single line
/foo.bar/s.test('foo\nbar');
// Regex Lookbehind Assertions
/(?<=\D)\d/
/(?<!\D)\d/
// Regex Unicode Property Escapes
// \p{UnicodePropertyName=UnicodePropertyValue}
// General_Category, Script, Script_Extensions
//
// \p{LoneUnicodePropertyNameOrValue}
// Alphabetic, Uppercase, Lowercase, White_Space, Noncharacter_Code_Point, Default_Ignorable_Code_Point, Any, ASCII, Assigned, ID_Start, ID_Continue, Join_Control, Emoji_Presentation, Emoji_Modifier, Emoji_Modifier_Base
//
// http://unicode.org/Public/UNIDATA/PropertyValueAliases.txt
// http://unicode.org/Public/UNIDATA/PropertyAliases.txt
// http://unicode.org/reports/tr18/#RL1.2
/^\p{Decimal_Number}+$/u.test('𝟏𝟐𝟑𝟜𝟝𝟞𝟩𝟪𝟫𝟬𝟭𝟮𝟯𝟺𝟻𝟼')

// Object Rest/Spread
const {a,...rest} = {a:1,b:2,...{c:3}}

// Promise#finally
Promise.prototype.finally;

// Asynchronous Iteration
// [Symbol.asyncIterator]
for await (const line of readLines()) {
console.log(line);
}
async function* readLines(){
yield await Promise.resolve('Line 1')
yield 'Line 2'
}

ECMAScript 2017

Object.values;
Object.entries;

'1'.padEnd(4, ' ');
'1'.padStart(4, ' ');

Object.getOwnPropertyDescriptors;

// 方法参数容许多余逗号
console.log(true);

// async,await
async function run() {
await Promise.resolve();
}

ECMAScript 2016

Array.prototype.includes;

// Exponentiation
1 ** 2; // Math.pow(1,2)

ECMAScript 2015

// array function
() => 1;

// let, const
let a = 1;
const b = 1;

// for-of
for (const v of [1]);

// Map, Set
new Map();
new Set();

// Symbol
const mySym = new Symbol();

// class
class Car {
constructor() {}
}

// promise
Promise.resolve();

// 默认参数, rest 参数
function hello(name = 'world', ...props) {}

const { a, b } = { a: 1, b: 2 };

String.prototype.includes;
String.prototype.startsWith;
String.prototype.endsWith;

Array.from('abc');
[(1, 2)].keys();
[(1, 2)].find((v) => v == 1);
[(1, 2)].findIndex((v) => v == 1);

Math.trunc;
Math.sign;
Math.cbrt;
Math.log2;
Math.log10;

Number.isInteger;
Number.isSafeInteger;

isFinite(1 / 0);
isNaN(false);

ECMAScript 5

'use strict';

'Hello'.charAt(0);
'Hello'[0];

// 多行 string
console.log(
'Hello \
Wener!',
);

// 允许关键字作为属性名
const a = { new: 'yes' };

String.prototype.trim;

Array.isArray([]);
Array.prototype.forEach;
Array.prototype.map;
Array.prototype.filter;
Array.prototype.reduce;
Array.prototype.reduceRight;
Array.prototype.every;
Array.prototype.some;
Array.prototype.indexOf;
Array.prototype.lastIndexOf;

JSON.parse('{}');
JSON.stringify({});

Date.now();
Date.prototype.toISOString;
Date.prototype.toJSON;

// getter,setter
const a = {
get name() {
return '';
},
set name(v) {
console.log(v);
},
};

// mgmt
Object.create;
Object.defineProperty;
Object.defineProperties;
Object.getOwnPropertyDescriptor;
Object.getOwnPropertyNames;
Object.getPrototypeOf;
Object.keys;
// protect
Object.preventExtensions;
Object.isExtensible;
Object.seal;
Object.isSealed;
Object.freeze;
Object.isFrozen;

// 允许多余逗号
// {a:1,}
// [1,]