跳到主要内容

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
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
👀
syntaxChromeNameNote
?.Chrome80Optional chaining
??Chrome80Nullish coalescing operator
??=Chrome85Nullish coalescing assignment
#nameChrome74Private class fields
usingExplicit Resource ManagementTS 5.2
featVersionnote
globalThisChrome71, NodeJS12

ECMAScript 2023

  • findLast, findLastIndex
    • {Array, %TypedArray%}.prototype.findLastIndex
    • {Array, %TypedArray%}.prototype.findLast
  • Hashbang Grammar - JS 直接作为可执行脚本
#!/usr/bin/env node

ECMAScript 2022

// 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

  • 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

// 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

  • JSON superset
    • U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR
  • Function.prototype.toString revision
  • Well-formed JSON.stringify
    • 避免返回错误 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,]