距离 第一次听到 节流与防抖 已经过去两年的时间,最近也是新看到一道题重新复习下老的知识点,并且提出新的解决方案。
# 先温习一下之前已经知道的经典方法:
// 节流 高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
exports.throttle = function (fn, limit = 1000) {
let flag = true;
return function () {
if (!flag) {
return;
}
flag = false;
setTimeout(() => {
fn.apply(this, arguments);
flag = true;
}, limit);
};
}
// 防抖 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
exports.debounce = function (fn, limit = 1000) {
let flag = null;
return function () {
clearTimeout(flag);
flag = setTimeout(() => {
fn.apply(this, arguments);
}, limit);
};
}
# 下面抛出新抛出的问题,如何用 @decorator装饰器
来实现呢?
装饰者模式就是动态的给类或对象增加功能的设计模式。虽然在浏览器中还没有被实现,但在TypeScript里已做为一项实验性特性予以支持。
安装TS、调试步骤之类的过程略去,可以参考handbook;下面小记一下decorator的重点:Decorators的实现使用了ES5的 Object.defineProperty 方法,这三个参数也和这个方法的参数一致。装饰器的本质就是一个函数语法糖,通过Object.defineProperty
来修改类中一些属性,descriptor
参数也是一个对象,是针对key
属性的描述符,里面有控制目标对象的该属性是否可写的writable属性等。
function throttle(limit: number = 0) {
let flag = true
return (target: any, key: string, descriptor: any) => {
let func = descriptor.value
descriptor.value = async (...args: any[]) => {
if(!flag) return
flag = false
try {
func.apply(this, ...args)
} catch (error) {
console.log(error)
}
if (!limit) return flag = true
setTimeout(() => {
flag = true
}, limit);
}
}
}
class TestD{
@throttle(2000)
fn() {
console.log('fn')
}
}
const testd = new TestD()
setInterval(testd.fn,50);
以上便完成了节流装饰器的操作,说好了问节流和防抖,转头就考了装饰器,老阴阳人了。
参考文档: