ECMAScript 是由 ECMA International 通过 TC39(技术委员会39)进行标准化的脚本语言规范,它是 JavaScript 语言的基础。JavaScript 是 ECMAScript 规范的一个实现。下面是 ECMAScript 标准的一些核心组成部分:
语法结构层
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中的
dateStyle和timeStyle配置项:处理多语言下的时间日期格式化的函数。