一个简单的防抖函数
function debounce(fn, interval = 300) {
let timeout = null;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, interval);
};
}
改写成TS
const debounce = (fn: (...args: any) => void, interval = 300) => {
let timeout: any = null;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, interval);
};
}
遇到问题
在ts版本中 arguments 变成了 undefined
溯源
JS版经过压缩后的版本
TS版经过编译压缩后的版本
这里有一个关键点:箭头函数没有自己的 arguments,它来自于其父作用域。在js编译压缩版本中,arguments 被重新指定了作用域。而在ts编译压缩版本,setTimeout中的箭头函数被替换成了function() {},但是没有同步修改 arguments 的作用域,这就导致了此时的 arguments 取到的是 setTimeout 中的无参函数的参数值,而不是实际需要的 return function 的参数值,自然就是返回 undefined 了
修复方案
const debounce = (fn: (...args: any) => void, interval = 300) => {
let timeout: any = null;
return function () {
// 用局部变量修改arguments作用域
const args: any = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, args);
}, interval);
};
}
修改后的编译压缩版,可以看到 arguments 的作用域被重新指定,此时能够正确取到需要的参数列表