目录
[一、ES6+ 语法](#一、ES6+ 语法)
[1. let 和 const 变量声明](#1. let 和 const 变量声明)
[2. 箭头函数 () => {}](#2. 箭头函数 () => {})
[3. 模板字符串](#3. 模板字符串)
[4. 解构赋值](#4. 解构赋值)
[5. 默认参数](#5. 默认参数)
[6. 展开运算符 ...](#6. 展开运算符 ...)
[7. Promise 和 async/await 异步处理](#7. Promise 和 async/await 异步处理)
[8. 类(class)和继承](#8. 类(class)和继承)
[9. 模块导入导出 import 和 export](#9. 模块导入导出 import 和 export)
[10. Symbol 类型](#10. Symbol 类型)
[11. Map 和 Set 数据结构](#11. Map 和 Set 数据结构)
[12. 生成器函数 function*](#12. 生成器函数 function*)
[13. 可选链操作符 ?.](#13. 可选链操作符 ?.)
[14. 空值合并运算符 ??](#14. 空值合并运算符 ??)
[1.javascript原型链(经典函数构造器 + prototype)](#1.javascript原型链(经典函数构造器 + prototype))
[2.TypeScript 版本(class 语法)](#2.TypeScript 版本(class 语法))
[1. JavaScript 版本示例](#1. JavaScript 版本示例)
[2. TypeScript 版本示例](#2. TypeScript 版本示例)
[四、如何使用 TypeScript 构建类型安全的 DApp 项目](#四、如何使用 TypeScript 构建类型安全的 DApp 项目)
[1. 使用 TypeScript 定义智能合约接口类型](#1. 使用 TypeScript 定义智能合约接口类型)
[2. 使用 web3.js 或 ethers.js 连接以太坊并调用合约(示例用 ethers.js)](#2. 使用 web3.js 或 ethers.js 连接以太坊并调用合约(示例用 ethers.js))
[3. 使用 TypeScript 定义事件类型并监听合约事件](#3. 使用 TypeScript 定义事件类型并监听合约事件)
[4. 使用类型安全的 ABI 绑定工具(如 TypeChain)](#4. 使用类型安全的 ABI 绑定工具(如 TypeChain))
[5. 总结](#5. 总结)
[1. 泛型函数示例](#1. 泛型函数示例)
[2. 泛型接口示例](#2. 泛型接口示例)
[3. 泛型类示例](#3. 泛型类示例)
[4. 泛型约束示例](#4. 泛型约束示例)
[1. TypeScript 接口示例](#1. TypeScript 接口示例)
[2. JavaScript 中模拟接口(无类型检查)](#2. JavaScript 中模拟接口(无类型检查))
[📌 一、装饰器是什么?](#📌 一、装饰器是什么?)
[🧪 二、类装饰器示例](#🧪 二、类装饰器示例)
[✅ 解释:](#✅ 解释:)
[📦 三、方法装饰器示例](#📦 三、方法装饰器示例)
[✅ 解释:](#✅ 解释:)
[🏷️ 四、属性装饰器示例](#🏷️ 四、属性装饰器示例)
[✅ 解释:](#✅ 解释:)
[📌 五、装饰器的应用场景](#📌 五、装饰器的应用场景)
一、ES6+ 语法
"ES6+ 语法"指的是 ECMAScript 2015(即 ES6)及其之后版本的 JavaScript 语言新特性和语法。简单说,就是现代 JavaScript 的新语法和功能。
常见 ES6+ 语法包括:
-
let
和const
变量声明 -
箭头函数
() => {}
-
模板字符串
Hello ${name}
-
解构赋值
-
默认参数
-
展开运算符
...
-
Promise 和 async/await 异步处理
-
类(class)和继承
-
模块导入导出
import
和export
-
Symbol 类型
-
Map 和 Set 数据结构
-
生成器函数
function*
-
可选链操作符
?.
-
空值合并运算符
??
1. let
和 const
变量声明
let a = 10; // 可变变量
const b = 20; // 常量,不能重新赋值
// b = 30; // 会报错
解释: let
声明的变量有块级作用域,const
声明常量,值不能变。
2. 箭头函数 () => {}
const add = (x, y) => x + y;
console.log(add(2, 3)); // 5
解释: 箭头函数写法简洁,并且不绑定自己的 this
。
3. 模板字符串
const name = 'Alice';
console.log(`Hello, ${name}!`); // Hello, Alice!
解释: 用反引号 ````` 包裹,可以直接嵌入变量和表达式。
4. 解构赋值
const person = {name: 'Bob', age: 25};
const {name, age} = person;
console.log(name, age); // Bob 25
const arr = [1, 2, 3];
const [first, second] = arr;
console.log(first, second); // 1 2
解释: 从对象或数组中快速提取值赋给变量。
5. 默认参数
function greet(name = 'Guest') {
console.log(`Hello, ${name}`);
}
greet(); // Hello, Guest
greet('Alice'); // Hello, Alice
解释: 函数参数可以设置默认值。
6. 展开运算符 ...
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4];
console.log(arr2); // [1, 2, 3, 4]
const obj1 = {a: 1, b: 2};
const obj2 = {...obj1, c: 3};
console.log(obj2); // {a:1, b:2, c:3}
解释: 展开数组或对象,合并或复制。
7. Promise 和 async/await 异步处理
// Promise
function fetchData() {
return new Promise(resolve => {
setTimeout(() => resolve('data'), 1000);
});
}
fetchData().then(data => console.log(data)); // data
// async/await
async function asyncFetch() {
const data = await fetchData();
console.log(data);
}
asyncFetch(); // data
解释: 用 Promise 处理异步,async/await 语法更简洁。
8. 类(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.`);
}
}
const d = new Dog('Rex');
d.speak(); // Rex barks.
解释: ES6 引入类语法,更接近传统面向对象。
9. 模块导入导出 import
和 export
// utils.js
export function sum(x, y) {
return x + y;
}
// main.js
import {sum} from './utils.js';
console.log(sum(2, 3)); // 5
解释: 支持模块化开发,导入导出代码片段。
10. Symbol 类型
const sym = Symbol('desc');
const obj = {};
obj[sym] = 'value';
console.log(obj[sym]); // value
解释: Symbol 是一种独一无二的标识符,常用作对象属性键,避免命名冲突。
11. Map 和 Set 数据结构
const map = new Map();
map.set('a', 1);
console.log(map.get('a')); // 1
const set = new Set([1, 2, 2, 3]);
console.log(set); // Set {1, 2, 3}
解释: Map 是键值对集合,Set 是无重复值的集合。
12. 生成器函数 function*
function* gen() {
yield 1;
yield 2;
yield 3;
}
const g = gen();
console.log(g.next().value); // 1
console.log(g.next().value); // 2
解释: 生成器可暂停执行,逐步产出值。
13. 可选链操作符 ?.
const obj = {a: {b: 10}};
console.log(obj.a?.b); // 10
console.log(obj.x?.b); // undefined 不报错
解释: 访问嵌套属性时安全,不会因中间值为 null 或 undefined 报错。
14. 空值合并运算符 ??
const foo = null ?? 'default';
console.log(foo); // default
const bar = 0 ?? 42;
console.log(bar); // 0
解释: 当左侧是 null 或 undefined 时,返回右侧值。
二、Javascript闭包
闭包(Closure)示例
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
}
}
const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
解释:
-
函数
outer
返回了一个内部函数inner
。 -
inner
函数可以访问outer
的变量count
,即使outer
已经执行完毕。 -
这种函数和其访问的变量环境形成的组合,就叫闭包。
-
闭包常用来实现私有变量和数据封装。
三、原型链
1.javascript原型链(经典函数构造器 + prototype)
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
const alice = new Person('Alice');
alice.sayHello(); // Hello, my name is Alice
console.log(alice.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
解释:
-
每个对象都有一个内部属性
[[Prototype]]
(常用__proto__
访问),指向它的原型对象。 -
当访问对象的属性或方法时,如果自身没有,会沿着
[[Prototype]]
一层层往上找,这个查找链就是原型链。 -
上面例子中,
alice
访问sayHello
方法时没在自身属性里找到,就去它的原型对象Person.prototype
查找。 -
Person.prototype
的原型是Object.prototype
,这构成了原型链的多层关系。 -
Object.prototype
的原型是null
,链条终点。
2.TypeScript 版本(class 语法)
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
}
const alice = new Person('Alice');
alice.sayHello(); // Hello, my name is Alice
console.log(Object.getPrototypeOf(alice) === Person.prototype); // true
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null
解释:
-
TypeScript 使用
class
关键字声明类,语法更现代,代码更清晰。 -
sayHello
是类的方法,实际挂载在Person.prototype
上,实例通过原型链访问。 -
Object.getPrototypeOf()
用来获取对象的原型,效果和__proto__
类似,但更标准安全。 -
原型链关系和JavaScript版本完全一样:实例原型 → 类的
prototype
→Object.prototype
→null
。
3.总结
-
JavaScript版本用构造函数和显式原型,适合传统理解原型链机制。
-
TypeScript版本用类语法,更符合现代代码风格,本质上还是基于JavaScript原型链实现。
三、作用域链
作用域链简介
-
作用域链是当访问一个变量时,JavaScript 引擎从当前作用域开始,逐级向上查找变量的过程。
-
这保证了内层函数可以访问外层函数的变量。
-
作用域链和原型链不同,作用域链是关于变量查找的执行环境机制。
1. JavaScript 版本示例
function outer() {
const a = 10;
function inner() {
const b = 20;
console.log(a + b); // 30
}
inner();
}
outer();
解释:
-
inner
函数内部访问变量a
,它不在自身作用域中。 -
于是它查找外层作用域
outer
,找到了变量a
,然后计算并输出结果。 -
这就是作用域链:
inner
→outer
→ 全局。
2. TypeScript 版本示例
TypeScript 的作用域链机制和 JavaScript 一样:
function outer() {
const a: number = 10;
function inner() {
const b: number = 20;
console.log(a + b); // 30
}
inner();
}
outer();
解释:
-
语法和JavaScript几乎一致,只是变量类型显式声明了。
-
作用域链机制完全相同,内层函数能访问外层函数的变量。
总结
-
作用域链保证了变量从内层到外层逐级查找。
-
它是运行时上下文环境的一部分,和闭包密切相关。
-
JavaScript 和 TypeScript 的作用域链规则一致,TS 只是加了类型。
四、如何使用 TypeScript 构建类型安全的 DApp 项目
下面给你关于"使用 TypeScript 构建类型安全的 DApp(去中心化应用)项目"的几个核心知识点,附带简短代码示例和解释。
1. 使用 TypeScript 定义智能合约接口类型
// 定义智能合约函数的接口
interface MyContract {
methods: {
balanceOf(address: string): { call(): Promise<string> };
transfer(to: string, amount: string): { send(): Promise<void> };
};
}
解释:
通过接口定义智能合约方法,确保调用时参数类型和返回类型明确,减少错误。
2. 使用 web3.js 或 ethers.js 连接以太坊并调用合约(示例用 ethers.js)
import { ethers } from 'ethers';
async function getBalance(contract: MyContract, address: string): Promise<string> {
const balance = await contract.methods.balanceOf(address).call();
return balance;
}
解释:
函数参数用类型接口约束 contract
,保证传入合约实例符合预期方法,address
是字符串。
3. 使用 TypeScript 定义事件类型并监听合约事件
interface TransferEvent {
from: string;
to: string;
value: string;
}
contract.on('Transfer', (from: string, to: string, value: string) => {
const event: TransferEvent = { from, to, value };
console.log('Transfer event:', event);
});
解释:
定义事件结构接口,事件监听回调参数用类型标注,方便后续类型检查和自动补全。
4. 使用类型安全的 ABI 绑定工具(如 TypeChain)
// 生成的合约类型(伪代码)
import { MyContract } from './types';
const contract: MyContract = getContractInstance();
const result = await contract.balanceOf('0x123...');
解释:
TypeChain 等工具根据合约 ABI 自动生成 TypeScript 类型,调用合约更安全,减少运行时错误。
5. 总结
-
用 TypeScript 接口和类型定义合约方法和事件,保证调用和监听的类型安全。
-
使用 ethers.js 或 web3.js 结合类型定义调用智能合约。
-
通过 TypeChain 等工具生成合约类型代码,减少手写错误。
五、泛型
概念
泛型可以让函数、类或接口在使用时指定类型,而不是在定义时就固定死,提高了代码复用性和类型安全。
JavaScript 本身没有泛型,泛型是 TypeScript(以及其他静态类型语言)提供的类型系统特性,用来增强代码的类型安全和复用性。
简单来说:
-
JavaScript 是动态类型语言,变量和函数的参数类型在运行时确定,没有静态类型检查。
-
TypeScript 在 JavaScript 基础上加了类型系统,其中就包括泛型,可以在编译阶段帮你检查类型,避免运行时错误。
所以,泛型是 TypeScript 的特色,JavaScript 没有对应的语法和概念。
1. 泛型函数示例
function identity<T>(arg: T): T {
return arg;
}
const str = identity<string>('hello'); // str 类型是 string
const num = identity<number>(123); // num 类型是 number
解释:
-
identity
是一个泛型函数,<T>
是类型参数,代表调用时传入的具体类型。 -
传入参数和返回值类型都与
T
一致,调用时指定类型,保证类型安全且复用性强。
2. 泛型接口示例
interface Box<T> {
value: T;
}
const box1: Box<string> = { value: 'hello' };
const box2: Box<number> = { value: 100 };
解释:
-
Box
是一个泛型接口,成员value
的类型由外部指定。 -
方便用同一个接口定义不同类型的对象。
3. 泛型类示例
class Stack<T> {
private items: T[] = [];
push(item: T) {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
}
const stack = new Stack<number>();
stack.push(10);
console.log(stack.pop()); // 10
解释:
-
泛型类
Stack
支持存放任何类型的元素,且保证类型一致性。 -
实例化时指定具体类型,保证操作时类型安全。
4. 泛型约束示例
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
loggingIdentity('hello'); // 输出 5
loggingIdentity([1, 2, 3]); // 输出 3
// loggingIdentity(123); // 报错,number 没有 length 属性
解释:
-
泛型约束保证传入的类型必须有
length
属性。 -
防止传入不符合约束的类型。
六、接口
概念
接口用于定义对象的结构,让代码更规范,可扩展性更好。
1. TypeScript 接口示例
interface User {
id: number;
name: string;
email?: string; // 可选属性
}
function greet(user: User) {
console.log(`Hello, ${user.name}`);
}
const user1 = { id: 1, name: 'Alice' };
greet(user1);
解释:
-
interface User
定义了一个结构类型,规定对象必须有id
和name
,email
可选。 -
函数
greet
形参要求是User
类型,确保传入对象符合接口。
2. JavaScript 中模拟接口(无类型检查)
JavaScript 没有接口,但你可以用约定或运行时检查实现类似效果:
function greet(user) {
if (typeof user.id !== 'number' || typeof user.name !== 'string') {
throw new Error('Invalid user object');
}
console.log(`Hello, ${user.name}`);
}
const user1 = { id: 1, name: 'Alice' };
greet(user1);
解释:
-
通过函数内部手动检查对象属性类型,保证参数符合预期结构。
-
但没有编译时类型检查,容易出错且不够方便。
总结:
-
TypeScript接口:静态类型检查,定义对象结构,是编译时用来提升代码健壮性的工具。
-
JavaScript:无接口概念,只能靠编码习惯和运行时检测保证对象结构。
应用场景
-
API 数据模型定义
-
前后端数据类型统一
-
高度协作项目中约定字段结构
七、装饰器
下面是 TypeScript 中的 装饰器(Decorator) 的讲解、使用条件、代码示例和解释。
📌 一、装饰器是什么?
装饰器是对类、方法、属性或参数的增强,是元编程的一种形式。需要在 tsconfig.json
中开启 experimentalDecorators
。
装饰器是 一种特殊的语法 ,用于 修改类、类方法、属性或参数的行为。它本质上是一个函数。
装饰器是 TypeScript 的高级功能之一,需要在 tsconfig.json
中启用:
{
"compilerOptions": {
"experimentalDecorators": true
}
}
🧪 二、类装饰器示例
function Logger(constructor: Function) {
console.log('Class decorated:', constructor.name);
}
@Logger
class User {
constructor(public name: string) {}
}
✅ 解释:
-
@Logger
是一个类装饰器。 -
它接收构造函数作为参数,在类定义时执行。
-
装饰器不会改变类本身行为,但可以扩展、增强或者记录日志。
📦 三、方法装饰器示例
function LogMethod(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const original = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Method ${propertyKey} called with`, args);
return original.apply(this, args);
};
}
class MathTool {
@LogMethod
add(a: number, b: number) {
return a + b;
}
}
const tool = new MathTool();
tool.add(2, 3); // 控制台打印日志
✅ 解释:
-
@LogMethod
修改add
方法,使其在执行前打印参数。 -
可以用于日志记录、性能分析、权限验证等。
🏷️ 四、属性装饰器示例
function ReadOnly(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
writable: false,
});
}
class Person {
@ReadOnly
name = 'Alice';
}
const p = new Person();
// p.name = 'Bob'; // ❌ 会失败(只读)
✅ 解释:
@ReadOnly
将属性设置为只读。
📌 五、装饰器的应用场景
-
日志打印(如方法调用参数)
-
权限控制
-
数据校验
-
自动绑定(如 Vue、NestJS 中常见用法)
-
AOP(面向切面编程)
-
NestJS 控制器、服务模块增强
-
Web3 签名校验封装
八、Javascript事件循环-eventloop
下面我将全面地给你讲清 JavaScript 的事件循环(Event Loop)机制 ,包括浏览器环境下的执行流程,并结合同步/异步、宏任务/微任务、Promise/定时器等概念,做到既清晰又实用。
🧠 1、JavaScript 是单线程语言
JavaScript 引擎只有一个主线程,不能同时干多件事,所以就需要一种机制来有序执行异步任务,这就是:
事件循环(Event Loop)
🔁 2、事件循环的基本流程(浏览器中)
-
所有代码进入主线程执行(同步代码)。
-
异步任务(如
setTimeout
、fetch
、Promise
、事件监听)被分发到对应的任务队列中。 -
主线程空了以后,事件循环会按照先"微任务队列",再"宏任务队列"的顺序执行异步任务。
-
每执行完一轮宏任务(一次主线程执行 + 所有微任务清空),就称为一个 tick。
📦 3、任务分类:宏任务 vs 微任务
分类 | 常见 API 示例 | 执行时机 |
---|---|---|
宏任务 | setTimeout 、setInterval 、setImmediate 、requestAnimationFrame 、I/O |
每次 Event Loop 循环 |
微任务 | Promise.then 、catch 、finally 、MutationObserver 、queueMicrotask |
宏任务后立即执行 |
🧪 4、经典例子讲清执行顺序
console.log('script start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('promise1');
}).then(() => {
console.log('promise2');
});
console.log('script end');
✅ 输出顺序:
script start
script end
promise1
promise2
setTimeout
✅ 原因:
-
console.log('script start')
是同步 → 立即执行 -
setTimeout
是宏任务 → 放入任务队列,稍后执行 -
Promise.then
是微任务 → 放入微任务队列 -
console.log('script end')
是同步 → 立即执行 -
主线程空了 → 执行微任务队列(
promise1
,promise2
) -
微任务清空 → 执行宏任务(
setTimeout
)
📊 5、流程图(简化版)
↓ 执行同步代码(主线程)
事件循环 → 执行所有微任务队列
↓
渲染页面(可选)
↓
执行一个宏任务
↓
重复事件循环
🛠 6、延伸技巧
📌 queueMicrotask
:手动添加微任务
queueMicrotask(() => {
console.log('microtask');
});
比 setTimeout(fn, 0)
还要早执行!
📌 await
本质上是微任务
async function foo() {
console.log('start');
await null;
console.log('end');
}
foo();
console.log('after');
输出:
start
after
end
🤔 7、Node.js 的事件循环与浏览器略有不同
Node.js 的事件循环分了更多阶段(如 timers、I/O callbacks、check 等),如果你需要我可以单独讲。
如果你希望:
-
通过图形化理解整个流程
-
或想练习几道面试题
-
或结合浏览器 DevTools 分析微任务执行
我也可以帮你准备,告诉我你的具体需求!
九、Javascript事件循环-宏任务-微任务
十、Javascript练习时间循环的网站推荐
十一、js面试题里的事件循环和nodejs事件循环是一个东西吗
Node.js 和 浏览器中 JavaScript 的事件循环机制看起来类似,但在底层实现 和任务处理模型方面存在关键区别。下面我们从结构图 + 概念 + 代码示例来系统讲解。
🧠 1️⃣ 概念区别:Node.js vs 浏览器事件循环
特性 | 浏览器(JS引擎) | Node.js(基于 libuv) |
---|---|---|
宿主环境 | 浏览器(Chrome, Firefox, etc) | Node.js(V8 + libuv) |
宏任务队列 | setTimeout 、setInterval 、XHR 等 |
setTimeout 、setImmediate 、I/O 回调 |
微任务队列 | Promise.then 、MutationObserver |
Promise.then 、process.nextTick |
事件循环阶段数 | 简单两队列(宏任务 & 微任务) | 6个阶段:timers → pending → idle → poll → check → close |
特有机制 | 页面渲染、浏览器API、DOM 操作 | 文件系统、网络请求、TCP/UDP、子进程、线程池 |
微任务优先级 | Promise 优先 |
process.nextTick > Promise.then |
执行顺序可控性 | 宏/微任务顺序比较直观 | 顺序更复杂,受 libuv 控制 |
🖼️ 2️⃣ 图示对比
📌 浏览器事件循环流程:
┌────────────────────┐
│ 宏任务队列 │ ← setTimeout / setInterval / I/O
└─────────┬──────────┘
↓
执行栈(call stack)
↑
┌─────────┴──────────┐
│ 微任务队列 │ ← Promise.then / MutationObserver
└────────────────────┘
👉 微任务会在当前宏任务执行结束后、下一个宏任务开始前全部执行完。
📌 Node.js 事件循环 6 阶段(来自 libuv)
┌────────────────────────────┐
│ timers 阶段 │ ← setTimeout、setInterval
├────────────────────────────┤
│ pending callbacks │ ← I/O错误回调
├────────────────────────────┤
│ idle, prepare 阶段 │
├────────────────────────────┤
│ poll 阶段 │ ← 等待I/O事件、读取文件等
├────────────────────────────┤
│ check 阶段 │ ← setImmediate 回调
├────────────────────────────┤
│ close callbacks │ ← 如 socket.on('close', ...)
└────────────────────────────┘
💡每个阶段执行后,都会检查并清空微任务队列 (nextTick
和 Promise.then
)
🧪 3️⃣ 示例代码对比:Node.js 与 浏览器中事件顺序
Node.js 示例
// node_event_loop.js
setTimeout(() => {
console.log('setTimeout');
});
setImmediate(() => {
console.log('setImmediate');
});
process.nextTick(() => {
console.log('process.nextTick');
});
Promise.resolve().then(() => {
console.log('Promise.then');
});
🧾 输出顺序通常为:
process.nextTick
Promise.then
setTimeout
setImmediate
浏览器中的类似代码
// browser_event_loop.html
setTimeout(() => {
console.log('setTimeout');
});
Promise.resolve().then(() => {
console.log('Promise.then');
});
queueMicrotask(() => {
console.log('queueMicrotask');
});
🧾 浏览器输出顺序:
Promise.then
queueMicrotask
setTimeout
📌 没有 process.nextTick
和 setImmediate
,微任务只包括 Promise
和 queueMicrotask
。
📚 4️⃣ 总结对比重点
分类 | 浏览器 JS | Node.js |
---|---|---|
微任务执行顺序 | Promise.then 等 |
process.nextTick → Promise |
独有机制 | DOM、WebAPI | setImmediate 、libuv 阶段模型 |
事件循环控制结构 | 简单宏/微任务 | 6阶段循环,每阶段后执行微任务 |
定时器精度 | 稳定,受浏览器控制 | 若有 I/O 操作,setTimeout 可能延迟 |
使用场景 | 前端交互 | 服务端、I/O密集、非阻塞操作 |
如你需要结合 Node.js 的 libuv 源码分析 或 浏览器的 requestAnimationFrame 渲染机制对比,我也可以继续展开。是否要配合图形化可视化执行流程模拟工具?