一文掌握 ECMAScript 的进化史:从 ES3 到 ES2024 的特性与用法

ECMAScript特性全面解读(从ES3到ES2024)

1. ECMAScript 3 (ES3) - 1999年

ES3是第一个正式发布的版本,主要对JavaScript的核心语法和功能进行了规范化,增强了语言的稳定性和扩展性。

特性

  • 正则表达式支持: 在ES3中,JavaScript引入了对正则表达式的支持。

示例

javascript 复制代码
// 使用正则表达式匹配字符串
const str = "Hello, world!";
const regex = /world/;
console.log(regex.test(str));  // 输出 true
  • 异常处理 : ES3引入了try...catch结构用于错误处理。
javascript 复制代码
try {
    throw new Error("Something went wrong!");
} catch (e) {
    console.error(e.message);  // 输出 Something went wrong!
}

2. ECMAScript 5 (ES5) - 2009年

ES5对JavaScript进行了重要的增强,引入了严格模式、数组和对象的方法、JSON支持等。

特性

  • 严格模式(Strict Mode)strict mode使得JavaScript运行更加严格,避免了一些潜在的错误。
javascript 复制代码
"use strict";
x = 10;  // 会抛出错误,x未定义
  • Object.defineProperty(): 允许在对象上精细控制属性的定义,如是否可写、可枚举等。
javascript 复制代码
const obj = {};
Object.defineProperty(obj, 'name', {
    value: 'Alice',
    writable: false
});
console.log(obj.name);  // 输出 'Alice'
obj.name = 'Bob';  // 无法修改,因为属性不可写
console.log(obj.name);  // 输出 'Alice'
  • Array.prototype.forEach()map()filter()等方法: ES5为数组引入了很多常用的高阶方法。
javascript 复制代码
const arr = [1, 2, 3];
arr.forEach((num) => console.log(num));  // 输出 1, 2, 3

const doubled = arr.map(num => num * 2);
console.log(doubled);  // 输出 [2, 4, 6]

const even = arr.filter(num => num % 2 === 0);
console.log(even);  // 输出 [2]

3. ECMAScript 6 (ES6 / ES2015) - 2015年

ES6是JavaScript的一个重大版本,包含了很多新特性,大大提高了语言的功能性与简洁性。

特性

  • letconst: 新的变量声明方式,提供了块级作用域。
javascript 复制代码
let x = 10;
const y = 20;

x = 15;  // 可以修改
// y = 25;  // 会报错,因为const不能修改
  • 箭头函数 : 简化了函数的书写,并且this绑定方式不同于传统函数。
javascript 复制代码
const add = (a, b) => a + b;
console.log(add(2, 3));  // 输出 5
  • 类(class): 引入了类的概念,简化了面向对象编程的方式。
javascript 复制代码
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    greet() {
        console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
    }
}

const person = new Person('Alice', 25);
person.greet();  // 输出 Hello, my name is Alice and I am 25 years old.
  • 模板字符串: 可以更方便地进行字符串拼接和多行字符串。
javascript 复制代码
const name = 'Alice';
const message = `Hello, ${name}!`;
console.log(message);  // 输出 Hello, Alice!
  • 解构赋值: 支持从数组或对象中提取值,简化了代码。
javascript 复制代码
const [a, b] = [1, 2];
console.log(a, b);  // 输出 1 2

const person = { name: 'Alice', age: 25 };
const { name, age } = person;
console.log(name, age);  // 输出 Alice 25
  • 模块化 : 引入了importexport语法,支持模块化编程。
javascript 复制代码
// file1.js
export const greeting = 'Hello, world!';

// file2.js
import { greeting } from './file1';
console.log(greeting);  // 输出 Hello, world!
  • Promise: 用于处理异步操作,使得异步代码更易于理解。
javascript 复制代码
const promise = new Promise((resolve, reject) => {
    const success = true;
    if (success) {
        resolve('Operation successful!');
    } else {
        reject('Operation failed.');
    }
});

promise
    .then(result => console.log(result))  // 输出 Operation successful!
    .catch(error => console.log(error));

4. ECMAScript 7 (ES7 / ES2016) - 2016年

ES7引入了相对较少的新特性,但仍有一些有用的增强。

特性

  • Array.prototype.includes(): 检查数组是否包含某个值。
javascript 复制代码
const arr = [1, 2, 3, 4];
console.log(arr.includes(3));  // 输出 true
console.log(arr.includes(5));  // 输出 false
  • 指数运算符(\**: 用于计算幂。
javascript 复制代码
console.log(2 ** 3);  // 输出 8

5. ECMAScript 8 (ES8 / ES2017) - 2017年

ES8引入了几个重要的新功能,特别是在异步编程方面的增强。

特性

  • async/await: 使得异步编程更简洁和直观。
javascript 复制代码
async function fetchData() {
    let response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
    let data = await response.json();
    console.log(data);
}

fetchData();
  • Object.entries()Object.values(): 返回对象的键值对数组或值数组。
javascript 复制代码
const obj = { a: 1, b: 2 };
console.log(Object.entries(obj));  // 输出 [['a', 1], ['b', 2]]
console.log(Object.values(obj));   // 输出 [1, 2]
  • String.prototype.padStart()String.prototype.padEnd(): 在字符串的开头或结尾填充指定字符,直到达到指定长度。
javascript 复制代码
const str = '5';
console.log(str.padStart(3, '0'));  // 输出 '005'
console.log(str.padEnd(3, '0'));    // 输出 '500'

6. ECMAScript 9 (ES9 / ES2018) - 2018年

ES9增强了正则表达式、异步编程和数组操作等方面。

特性

  • 异步迭代器: 支持异步操作中的迭代。
javascript 复制代码
async function* generateNumbers() {
    yield 1;
    yield 2;
    yield 3;
}

(async () => {
    for await (const num of generateNumbers()) {
        console.log(num);  // 输出 1, 2, 3
    }
})();
  • Object.fromEntries(): 用于将键值对数组转为对象。
javascript 复制代码
const entries = [['name', 'Alice'], ['age', 25]];
const obj = Object.fromEntries(entries);
console.log(obj);  // 输出 { name: 'Alice', age: 25 }

7. ECMAScript 10 (ES10 / ES2019) - 2019年

ES10引入了一些实用的新功能,特别是对于数组和字符串的操作。

特性

  • Array.prototype.flat()flatMap(): 用于将嵌套数组"拉平",或映射并扁平化。
javascript 复制代码
const arr = [1, [2, [3, [4]]]];
console.log(arr.flat(2));  // 输出 [1, 2, 3, [4]]

const mapped = arr.flatMap(x => [x, x * 2]);
console.log(mapped);  // 输出 [1, 2, 2, 4, 3, 6]
  • String.prototype.matchAll(): 返回正则表达式匹配的所有结果。
javascript 复制代码
const str = 'a1b2c3';
const regex = /\d/g;
const matches = str.match
All(regex);
for (const match of matches) {
    console.log(match);  // 输出 ["1", index: 1, input: "a1b2c3"]
}

8. ECMAScript 11 (ES11 / ES2020) - 2020年

ES11引入了对大整数(BigInt)和全局对象(globalThis)的支持。

特性

  • BigInt : 用于处理超出Number范围的整数。
javascript 复制代码
const bigInt = 1234567890123456789012345678901234567890n;
console.log(bigInt + 1n);  // 输出 1234567890123456789012345678901234567891n
  • globalThis: 标准化访问全局对象。
javascript 复制代码
console.log(globalThis);  // 输出全局对象

9. ECMAScript 12 (ES12 / ES2021) - 2021年

ES12引入了一些小而有用的特性,主要集中在语法增强和新方法。

特性
  • 逻辑赋值运算符 (&&=, ||=, ??=)

    ES12引入了逻辑赋值运算符,简化了条件赋值的代码书写。

javascript 复制代码
let x = 1;
x &&= 2;  // 如果 x 为真,则 x = 2
console.log(x);  // 输出 2

let y = null;
y ||= 3;  // 如果 y 为假,则 y = 3
console.log(y);  // 输出 3

let z;
z ??= 4;  // 如果 z 为 null 或 undefined,则 z = 4
console.log(z);  // 输出 4
  • 数字分隔符(Numeric Separators)

    数字分隔符使用 _ 使长数字更易读。

javascript 复制代码
const billion = 1_000_000_000;
console.log(billion);  // 输出 1000000000
  • Promise.any()

    返回第一个成功的 Promise,如果所有 Promise 都失败,则返回一个包含所有错误的 AggregateError

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

Promise.any(promises).then(result => {
    console.log(result);  // 输出 "Success 1"
}).catch(error => {
    console.error(error);  // 如果全部失败,输出 AggregateError
});
  • WeakRefsFinalizationRegistry

    提供了一种引用弱对象的方式,避免内存泄漏。

javascript 复制代码
let obj = { name: 'Alice' };
const weakRef = new WeakRef(obj);
console.log(weakRef.deref());  // 输出 { name: 'Alice' }

obj = null;  // 引用被删除
console.log(weakRef.deref());  // 输出 undefined

10. ECMAScript 13 (ES13 / ES2022) - 2022年

ES13增强了异步和类的功能,优化了数组的操作。

特性
  • 顶级await

    允许在模块的顶层直接使用 await,无需放在异步函数中。

javascript 复制代码
const data = await fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(response => response.json());
console.log(data);
  • 类字段声明

    ES13允许在类中直接声明字段,而无需放在构造函数中。

javascript 复制代码
class Person {
    name = 'Alice';  // 类字段
    age = 25;

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

const person = new Person();
console.log(person.name);  // 输出 "Alice"
  • Error.cause

    Error 对象添加了 cause 属性,便于追踪错误来源。

javascript 复制代码
try {
    throw new Error('Main error', { cause: 'Invalid input' });
} catch (e) {
    console.log(e.message);  // 输出 "Main error"
    console.log(e.cause);    // 输出 "Invalid input"
}

11. ECMAScript 14 (ES14 / ES2023) - 2023年

ES14引入了一些针对数组和排序操作的优化。

特性
  • Array.prototype.at()

    支持使用负索引从数组末尾访问元素。

javascript 复制代码
const arr = [10, 20, 30, 40];
console.log(arr.at(-1));  // 输出 40
console.log(arr.at(-2));  // 输出 30
  • 数组查找方法:findLast()findLastIndex()

    从数组的末尾开始查找满足条件的元素或索引。

javascript 复制代码
const arr = [1, 2, 3, 4];
console.log(arr.findLast(x => x % 2 === 0));  // 输出 4
console.log(arr.findLastIndex(x => x % 2 === 0));  // 输出 3
  • 优化的 Array.prototype.sort()

    避免了原数组被修改的问题(如果浏览器支持此特性)。

javascript 复制代码
const arr = [3, 1, 4];
const sorted = arr.sort((a, b) => a - b);
console.log(arr);     // 原数组仍可能被修改(特性正在优化)
console.log(sorted);  // 输出排序后的数组

12. ECMAScript 15 (ES2024) - 2024年

ES15进一步增强了语言功能,引入了更多现代化特性。

特性
  • 类装饰器(Decorators)

    允许为类和类的成员添加装饰器,用于修改行为。

javascript 复制代码
function log(target, name, descriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args) {
        console.log(`Calling ${name} with`, args);
        return original.apply(this, args);
    };
    return descriptor;
}

class Calculator {
    @log
    add(a, b) {
        return a + b;
    }
}

const calc = new Calculator();
console.log(calc.add(2, 3));  // 输出日志,并返回 5
  • 异步可迭代增强

    改进了异步迭代器,使其更易用。

javascript 复制代码
async function* generate() {
    yield await Promise.resolve(1);
    yield await Promise.resolve(2);
    yield await Promise.resolve(3);
}

for await (const value of generate()) {
    console.log(value);  // 输出 1, 2, 3
}
  • 数组分组方法:group()groupToMap()

    根据指定规则将数组元素分组。

javascript 复制代码
const arr = ['apple', 'banana', 'cherry', 'date'];
const grouped = arr.group(item => item.length);
console.log(grouped);
// 输出 { 5: ['apple'], 6: ['banana', 'cherry'], 4: ['date'] }

总结

从ES3到ES2024,ECMAScript经历了从基础语法优化到现代语言功能的全面进化。以下是每个版本的亮点回顾:

  • ES3(1999):正则表达式、异常处理。
  • ES5(2009):严格模式、JSON支持、数组方法。
  • ES6(2015):模块化、类、Promise、箭头函数。
  • ES7 (2016):includes()、指数运算符。
  • ES8 (2017):async/awaitObject.entries()
  • ES9 (2018):异步迭代器、flat()
  • ES10 (2019):Object.fromEntries()matchAll()
  • ES11 (2020):BigIntglobalThis
  • ES12 (2021):逻辑赋值运算符、Promise.any()
  • ES13 (2022):顶级await、类字段。
  • ES14 (2023):findLast()at()
  • ES15(2024):类装饰器、分组方法。

以上内容覆盖了每个版本的重要特性和代码示例,便于全面理解ECMAScript的进化历程。如果需要更深入的某一部分特性解析,可以随时提问!如果有哪里解释的不到位, 也欢迎各位大神指正

相关推荐
午后书香6 天前
什么是数据劫持与事件委托?有什么用?
前端·javascript·ecmascript 6
poloma2 个月前
五千字长文搞清楚 Blob File ArrayBuffer TypedArray 到底是什么
前端·javascript·ecmascript 6
卡布鲁3 个月前
Promise深入理解:探索相关高级用法
javascript·ecmascript 6
小Bk6 个月前
“键值对大逃亡:Object.entries如何带领它们奔向数组自由”
前端·vue.js·ecmascript 6
要多努力才算好啊6 个月前
ES6标准入门 - Reflect
前端·ecmascript 6
睡着学7 个月前
ES6数据结构深度解析:Set, Map, WeakSet 和 WeakMap
前端·javascript·ecmascript 6
coding消烦员7 个月前
面试官:你知道 ES6 的 生成器 Generator 吗?小明:说起 Generator,还得从我上次去餐馆点餐开始说起
前端·javascript·ecmascript 6
睡着学8 个月前
干货满满:数据类型判断(4种方法)、call的底层逻辑和Object.prototype调用toString方法时的步骤
前端·javascript·ecmascript 6
eiko莉8 个月前
this指向谁,只需记住这几条绑定规则
javascript·面试·ecmascript 6