第 3 卷
71try { 72const result = onRejected(this.reason);
73result instanceof MyPromise ? result.then(resolve, reject) : resolve(result);
| 74 | } catch (error) { |
|---|---|
| 75 | reject(error); |
| 76 | } |
| 77 | }, 0); |
| 78 | } |
79
| 80 | //处理等待状态(异步操作未完成时,缓存回调函数) |
|---|---|
| 81 | if (this.status === PENDING) { |
| 82 | this.onFulfilledCallbacks.push(() => { |
| 83 | setTimeout(() => { |
总结
| 1. | new:创建新对象、绑定this、执行构造函数、判断返回值 |
|---|---|
| 2. | call/apply:临时挂载函数、绑定this、立即执行、清理环境,区别仅在参数形式 |
| 3. | bind:返回绑定this的新函数、支持柯里化、兼容new调用、维护原型链 |
- 简易Promise:维护三种不可逆转状态、执行器立即执行、 then 方法支持异步和链式调用、实现
值的穿透
六、手写防抖函数(debounce)
核心原理
- 防抖的核心是“延迟执行”:当函数被频繁触发时,只在最后一次触发后,等待指定时间再执行函
数
- 每次触发函数时,都清除之前设置的定时器,重新计时,避免函数多次执行
- 支持“立即执行”可选参数:开启后,第一次触发时立即执行函数,后续触发则重新延迟
- 支持“取消防抖”功能:可手动取消尚未执行的延迟函数
实现代码
Code block
1function debounce(fn, delay, immediate = false) { 2let timer = null; // 存储定时器ID
8 9// 每次触发都清除之前的定时器,重新计时
10if (timer) clearTimeout(timer);
11 12// 处理立即执行逻辑
13if (immediate && !isExecuted) { 14fn.apply(_this, args);
| 15 | isExecuted = true; //执行后标记为已执行 |
|---|---|
| 16 | } else { |
| 17 | //延迟执行逻辑 |
| 18 | timer = setTimeout(() => { |
| 19 | fn.apply(_this, args); |
| 20 | isExecuted = false; //延迟执行后重置标记,允许下次立即执行 |
| 21 | timer = null; //执行完毕清空定时器 |
| 22 | }, delay); |
| 23 | } |
| 24 | }; |
25 26// 取消防抖:手动清除定时器,重置状态
27debounced.cancel = function() {
| 28 | if (timer) clearTimeout(timer); |
|---|---|
| 29 | timer = null; |
| 30 | isExecuted = false; |
| 31 | }; |
32 33return debounced;
34} 35
36// 测试示例 37function handleInput(value) {
38console.log(`输入内容:${value}`);
39} 40
41// 1. 普通防抖(延迟500ms执行)
| 42 | const debouncedInput = debounce(handleInput, 500); |
|---|---|
| 43 | //模拟频繁输入(仅最后一次输入后500ms执行) |
| 44 | debouncedInput('a'); |
| 45 | debouncedInput('ab'); |
| 46 | debouncedInput('abc'); // 500ms后输出:输入内容:abc |
| 48 | // 2.立即执行防抖(第一次输入立即执行,后续输入延迟) |
| 49 | const immediateDebounce = debounce(handleInput, 500, true); |
| 55 | const cancelableDebounce = debounce(handleInput, 1000); |
|---|---|
| 56 | cancelableDebounce('需要取消'); |
| 57 | cancelableDebounce.cancel(); //手动取消,函数不会执行 |
58
七、手写节流函数(throttle)
核心原理
- 节流的核心是“控制执行频率”:当函数被频繁触发时,保证在指定时间内只执行一次函数
- 两种实现思路:
- 时间戳法:第一次触发立即执行,后续触发时判断当前时间与上次执行时间的差值,大于等于延
迟则执行
- 定时器法:第一次触发延迟执行,后续触发时若定时器存在则不执行,执行后清空定时器
- 合并两种思路,实现“第一次立即执行+后续固定频率执行”的完整节流效果
- 支持“取消节流”功能:手动取消尚未执行的延迟函数
实现代码
Code block
1function throttle(fn, interval) { 2let lastTime = 0; // 存储上次执行的时间戳
3let timer = null; // 存储定时器ID 4
5// 节流核心函数 6const throttled = function(...args) {
7const _this = this;
8const now = Date.now(); // 当前时间戳 9
| 10 | // 1.时间戳法:判断当前时间与上次执行时间的差值是否大于等于间隔 |
|---|---|
| 11 | if (now - lastTime >= interval) { |
| 12 | //清除可能存在的定时器(避免时间戳和定时器双重执行) |
| 13 | if (timer) { |
| 14 | clearTimeout(timer); |
| 15 | timer = null; |
| 17 | //执行函数,更新上次执行时间 |
| 18 | fn.apply(_this, args); |