2024 最新 ECMAScript 标准

503 阅读8分钟

image.png

ECMAScript 是由 ECMA International 通过 TC39(技术委员会39)进行标准化的脚本语言规范,它是 JavaScript 语言的基础。JavaScript 是 ECMAScript 规范的一个实现。下面是 ECMAScript 标准的一些核心组成部分:

语法结构层

image.png

1. 语言核心

1.1 变量声明

ECMAScript提供了三种变量声明方式,每种方式都有其作用域和生命周期的特点。

  • var:函数作用域或全局作用域,存在变量提升现象。
  • let:块级作用域,不存在变量提升,允许在相同作用域内重新声明。
  • const:块级作用域,用于声明常量,一旦声明必须初始化,且值不可更改。

1.2 数据类型

ECMAScript的数据类型分为原始类型和复合类型。

  • 原始类型:包括Undefined、Null、Boolean、Number、BigInt、String、Symbol。
  • 复合类型:主要是Object,包括Array、Function等,通过引用访问。

1.3 操作符

ECMAScript支持多种操作符,用于执行算术、比较、逻辑等操作。

  • 算术操作符:+、-、*、/、%、**(ES2020引入的指数运算符)。
  • 关系操作符:>、<、>=、<=、==、!=、===、!==。
  • 位操作符:&、|、^、~、<<、>>、>>>。
  • 逻辑操作符:&&、||、!。

1.4 控制语句

控制语句用于控制代码的执行流程。

  • 条件语句:if、switch。
  • 循环语句:for、while、do-while。
  • 跳转语句:break、continue、return。

1.5 函数

函数是执行代码块的引用,可以传递参数并返回结果。

  • 定义:使用function关键字或箭头函数语法。
  • 调用:通过函数名加括号和参数列表。
  • 参数传递:传值或传引用。
  • 函数作用域:函数内部声明的变量只能在此函数内部访问。

2. 类和对象

2.1 对象字面量

对象字面量是创建对象的简洁方式,由键值对组成。

let person = {
  name: "Kimi",
  age: 30,
  greet: function() {
    console.log(`Hello, my name is ${this.name}!`);
  }
};

2.2 类(ES6+)

ES6引入了类的概念,通过class关键字定义类,支持继承。

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} barks.`);
  }
}

2.3 继承(ES6+)

通过extends关键字实现继承,子类可以扩展或覆盖父类的方法。

class Cat extends Animal {
  speak() {
    console.log(`${this.name} meows.`);
  }
}

3. 标准库

3.1 内置对象

ECMAScript提供了多种内置对象,如Array、Object、Function、Date、Math等。

// Array 示例
let numbers = [1, 2, 3];
numbers.forEach((number) => console.log(number));

// Date 示例
let now = new Date();
console.log(now.toString());

3.2 集合

集合类型如Map、Set提供了新的数据结构,支持键值对和唯一值的存储。

// Map 示例
let map = new Map();
map.set("key", "value");
console.log(map.get("key"));

// Set 示例
let set = new Set();
set.add("value");
console.log(set.has("value"));

3.3 迭代器和生成器

迭代器允许遍历集合类型,生成器提供了一种懒加载数据的方式。

// 迭代器 示例
let iterable = {
  [Symbol.iterator]() {
    let values = [1, 2, 3];
    let index = 0;
    return {
      next() {
        if (index < values.length) {
          return { value: values[index++], done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
};

for (let value of iterable) {
  console.log(value);
}

// 生成器 示例
function* generateNumbers() {
  let n = 1;
  while (n <= 5) {
    yield n++;
  }
}

let generator = generateNumbers();
console.log(generator.next().value);

4. 模块

ECMAScript的模块系统允许代码的模块化开发,提高了代码的可维护性和可重用性。

// mathUtils.js
export function add(x, y) {
  return x + y;
}

export function subtract(x, y) {
  return x - y;
}

// app.js
import { add } from './mathUtils.js';
console.log(add(1, 2));

5. 异步编程

ECMAScript提供了Promise和Async/Await关键字,简化了异步编程。

// Promise 示例
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Done!");
  }, 1000);
});

promise.then((value) => {
  console.log(value);
});

// Async/Await 示例
async function fetchData() {
  let response = await fetch("https://api.example.com/data");
  let data = await response.json();
  console.log(data);
}

fetchData();

6. 错误处理

ECMAScript提供了try...catch语句来捕获和处理异常。

try {
  // 尝试执行的代码
  throw new Error("Something went wrong!");
} catch (error) {
  // 处理错误的代码
  console.error(error);
}

7. 反射

ECMAScript提供了Proxy和Reflect API,允许自定义对象的基本操作。

// Proxy 示例
let obj = {};
let handler = {
  get(target, property) {
    if (property === "name") {
      return "Kimi";
    }
  }
};

let proxy = new Proxy(obj, handler);
console.log(proxy.name); // "Kimi"

// Reflect API 示例
let obj = { name: "Kimi" };
let result = Reflect.set(obj, "age", 30);
console.log(result); // true

8. 国际化

ECMAScript提供了Intl对象,支持国际化相关的操作。

// Intl 示例
let number = 123456.789;
console.log(new Intl.NumberFormat("zh-CN").format(number)); // "123,456.789"

let date = new Date();
console.log(new Intl.DateTimeFormat("zh-CN").format(date)); // "2024/1/1"

9. JSON

ECMAScript提供了JSON对象,用于处理JSON数据的解析和序列化。

// JSON 示例
let jsonString = '{"name": "Kimi", "age": 30}';
let obj = JSON.parse(jsonString);
console.log(obj.name); // "Kimi"

let data = { name: "Kimi", age: 30 };
let jsonString = JSON.stringify(data);
console.log(jsonString); // '{"name":"Kimi","age":30}'

10. ECMAScript 2024 (ES15) 新特性详解

ECMAScript 2024 (ES15) 带来了一系列令人兴奋的新特性,这些特性将进一步增强JavaScript的表达力和开发效率。以下是ES15中一些关键的新特性:

10.1 Record和Tuple:不可变数据结构的革新

ECMAScript 2024引入了Record和Tuple,这两种新型的不可变数据结构,为对象和数组提供了不可变版本。这为函数式编程和状态管理带来了新的可能性。

Record 定义了一个不可变的对象结构,而 Tuple 则定义了一个不可变的数组结构。这些结构在尝试修改时会抛出错误,从而保证了数据的不变性。

const person = #{ name: "Alice", age: 30 }; // Record
const numbers = #[1, 2, 3, 4, 5]; // Tuple

// 尝试修改会抛出错误
// person.age = 31; // TypeError

优势

  • 保证数据不被意外修改,简化状态管理。
  • 通过结构共享提高内存使用效率。

劣势

  • 需要开发者深入理解不可变性概念。
  • 目前工具链支持可能不够完善。

适用场景:配置对象、常量数据集等不需要频繁修改的数据。

10.2 模式匹配:提升代码表达力

模式匹配是一种源自函数式编程语言的强大特性,它使得处理复杂数据结构变得更加直观和简洁。

const user = { name: "Alice", age: 25 };
const { name, age } = user;

优势

  • 提高代码可读性。
  • 减少数据提取和操作的样板代码。

劣势

  • 语法复杂度较高,可能需要一定学习成本。
  • 不恰当使用可能影响性能。

适用场景:处理复杂JSON数据、Redux reducer等需要进行复杂条件判断的场合。

10.3 Temporal API:日期时间处理的新标准

Temporal API是对现有Date对象的全面升级,提供了更精确、更易用的日期和时间处理方法。

优势

  • 更准确地处理闰秒、时区等复杂情况。
  • 简化日期时间的算术运算、解析和格式化。

劣势

  • 可能增加代码包大小。
  • 现有项目迁移成本较高。

适用场景:需要精确时间计算和时区支持的应用。

10.4 管道操作符:函数式编程的福音

管道操作符(|>)允许开发者以更加线性和可读的方式链接函数调用,这种语法在函数式编程中特别有用。

const result = "Hello, World!"
  |> str => str.toLowerCase()
  |> str => str.split('')
  |> arr => arr.reverse()
  |> arr => arr.join('');
console.log(result); // "!dlrow ,olleh"

优势

  • 提高函数组合的可读性。
  • 便于重构和维护长链式操作。

劣势

  • 新语法需要时间适应。
  • 工具支持可能需要更新。

适用场景:数据处理管道、多步骤转换操作等。

10.5 异步上下文:简化异步操作追踪

异步上下文提供了一种更优雅的方式来处理异步操作,特别是在需要跨多个异步调用保持上下文的场景中。

async function processOrder(orderId) {
  const context = new AsyncContext({ orderId });
  await AsyncContext.run(context, async () => {
    const order = await fetchOrder();
    await processPayment();
    await sendConfirmation();
    // 所有异步操作都可以访问到orderId,而无需显式传递
  });
}

优势

  • 简化异步操作的调试和追踪。
  • 保持异步调用间的上下文一致性。

劣势

  • 增加了理解异步流程的复杂度。
  • 某些情况下可能带来性能开销。

适用场景:复杂的异步流程,如涉及多个网络请求或I/O操作的应用。

10.6 增强的模块系统:灵活导入导出

新的模块系统提供了更多的灵活性和选项,包括条件导入和命名空间导入。

优势

  • 提供更多模块加载控制。
  • 通过条件加载潜在地减少包大小。

劣势

  • 增加了模块管理的复杂性。
  • 需要谨慎处理以确保与现有模块的兼容性。

适用场景:大型应用开发,特别是需要按需加载或更细粒度依赖控制的项目

11. ECMAScript 2024 (ES15) 新特性

  • Object.groupBy 和 Map.groupBy:提供了将可迭代对象分组为一个新的Map或对象的能力。
  • Atomics.waitAsync() :静态方法异步等待共享内存的特定位置并返回一个Promise,与Atomics.wait()不同,waitAsync是非阻塞的且可用于主线程。

12. ECMAScript 2023 新特性

  • findLast() 和 findLastIndex() :从头到尾搜索数组。
  • Hashbang 语法:允许在脚本开始处使用#!语法。
  • 通过副本更改数组:引入了toReversed()toSorted()toSpliced()with()方法。
  • Symbol 作为 WeakMap 的键:增强了WeakMap的键类型。

13. ECMAScript 2021 (ES12) 新特性

  • String.prototype.replaceAll:提供了一个新方法来替换字符串中所有匹配的子串。
  • Promise.any() :返回第一个fulfilled的promise,若全部reject,则返回一个带有失败原因的AggregateError。
  • 逻辑赋值操作符:如??=&&=||=
  • WeakRefs:使用弱引用对象,该弱引用不会阻止GC,并且可以在GC前使用WeakRef.prototype.deref()解除该引用。
  • 下划线 (_) 分隔符:使用_分隔数字字面量以方便阅读。
  • Intl.ListFormat:处理多语言相关的对象格式化操作。
  • Intl.DateTimeFormat API中的dateStyletimeStyle配置项:处理多语言下的时间日期格式化的函数。