「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」。
前言
大家好,我是轮子猫。本系列文章将带你使用 TDD 的方式每天花费 5 分钟,完成一个大厂笔试、面试必考手写题目。
- 防抖 ✅
- 节流 ✅
- call、apply、bind
- EventEmitter
- 手动实现 ES5 继承
- 手动实现 instanceof
- Object.create
- new
- 浅拷贝和深拷贝
- 单例模式
- 手动实现 JSONP
- 数组去重、扁平、最值
- 数组乱序 - 洗牌算法
- 函数柯里化
- 模拟实现 promise
- 基于 Promise 的 ajax 封装
- 异步循环打印
- 图片懒加载
需求
同样,在实现节流之前,我们先来了解一下节流的定义。节流指的是,每隔 n 秒,只执行一次函数。如果在 n 秒内多次触发函数 ,只有一次生效。 节流和防抖很像,不过,一般来说在 n 秒内连续触发事件,节流只在第一次触发有效。
现在我们来拆解一下需求:
- 每隔 n 秒,只执行一次函数:也就是延迟执行函数
- 函数在 n 秒被连续触发,只执行第一次触发的函数,忽略其他的触发事件。
实现
现在我们来一步一步实现节流。
需求 1
首先,我们先实现关于延迟执行函数的测试代码
// throttle.test.js
test('should dealy function', function(done) {
const mockFn = jest.fn();
const throttledFn = throttle(mockFn, 10);
throttledFn();
expect(mockFn.toBeCalledTimes(0);
setTimeout(function() {
expect(mockFn).toBeCalledTimes(1);
done();
}, 20);
})
运行测试代码
实现测试代码
// throttle.js
function throttle(fn, n) {
return function () {
setTimeout(function () {
fn();
}, n);
};
}
接着,我们继续运行测试代码
需求 2
现在,我们来实现拆解后的需求 2,测试代码如下
// throttle.test.js
test("should throttle function", function (done) {
const mockFn = jest.fn((val) => val);
const throttledFn = throttle(mockFn, 32);
let result;
throttledFn("a");
throttledFn("b");
expect(mockFn).toBeCalledTimes(0);
setTimeout(function () {
result = throttledFn("c");
expect(mockFn).toBeCalledTimes(1);
expect(result).toBe("a");
done();
}, 64);
});
实现
// throttle.js
function throttle(fn, n) {
let timer = null;
let val;
return function (...args) {
const context = this;
if (!timer) {
timer = setTimeout(function () {
timer = null;
val = fn.apply(context, args);
}, n);
}
return val;
};
}
最后,运行测试代码
这样,最基本的节流函数就已经成功实现了,收工!~