如何为函数属性编写节流装饰器?解决闭包与上下文问题
解决节流装饰器的this指向问题
你的问题核心是setTimeout回调里的this丢失了原方法的上下文,同时还有参数处理的小问题,修正方案如下:
方案1:使用箭头函数继承外层this
箭头函数不会绑定自身的this,会沿用外层函数的上下文,这里外层就是包装方法的this(也就是类实例):
function throttle(timecount) { return function (value, { name, kind }) { const origin = value; if (kind === 'method') { return function (...args) { // 用剩余参数收集所有调用参数 setTimeout(() => { origin.apply(this, args); // 箭头函数继承外层的this }, timecount); }; } }; } class D { message = "hello!"; @throttle(1000) m() { console.log('execute', this.message); } } const y = new D(); y.m(); // 1秒后输出 "execute hello!"
方案2:提前保存上下文到变量
如果需要兼容不支持箭头函数的环境,可以在包装函数里把this存到变量,在setTimeout回调里使用这个变量:
function throttle(timecount) { return function (value, { name, kind }) { const origin = value; if (kind === 'method') { return function (...args) { const self = this; // 保存当前实例的上下文 setTimeout(function () { origin.apply(self, args); // 使用保存的上下文 }, timecount); }; } }; }
额外注意点
- 原代码里
setTimeout的回调函数声明了args参数,会覆盖外层的args,导致传递给原方法的参数错误,必须去掉这个参数。 - 包装函数的参数要用
...args剩余语法收集所有调用参数,保证原方法能接收到正确的参数。
内容的提问来源于stack exchange,提问作者Eric Wang
相关产品推荐
相关产品推荐

