在使用原生JavaScript实现节流函数时,开发者经常会遇到调用apply方法后函数没有按预期执行的情况,这往往和节流函数的实现逻辑、上下文绑定以及参数传递方式有关。

常见的节流函数实现示例
先来看一个基础的节流函数实现,这也是很多开发者遇到apply失效问题的场景:
// 基础节流函数实现
function throttle(fn, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
}
}
// 使用示例
const button = document.getElementById('btn');
button.addEventListener('click', throttle(function() {
console.log('按钮被点击', this);
}, 1000));
apply方法失效的常见原因
1. 节流返回函数的上下文丢失
如果节流函数返回的新函数被赋值给其他变量,或者被作为回调传递给不支持绑定上下文的方法,那么内部调用apply时的this可能就不是预期的对象。比如下面的错误用法:
function throttle(fn, delay) {
let lastTime = 0;
// 没有用function声明返回函数,而是用了箭头函数,导致this继承外层上下文
return (...args) => {
const now = Date.now();
if (now - lastTime >= delay) {
// 此时this不是调用节流函数的上下文,apply绑定无效
fn.apply(this, args);
lastTime = now;
}
}
}
箭头函数没有自己的this,会继承外层作用域的this,所以在返回函数执行时,this可能不是我们期望的绑定对象,导致apply绑定的上下文失效。
2. 参数传递不符合apply要求
apply方法要求第二个参数是数组或者类数组对象,如果传递的参数不是正确格式,也会导致函数执行异常,看起来像是apply失效。比如下面的错误写法:
function throttle(fn, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
// 错误传递参数,没有把args作为数组传给apply
fn.apply(this, ...args);
lastTime = now;
}
}
}
这里把args展开后传递,不符合apply对第二个参数的要求,会导致参数传递错误,函数无法正确执行。
3. 节流逻辑导致函数没有被执行
有时候看起来是apply失效,其实是节流的时间判断逻辑有问题,导致函数根本没有被执行。比如delay设置错误,或者lastTime的初始值设置不当:
function throttle(fn, delay) {
let lastTime = Date.now(); // 初始值设为当前时间,第一次点击不会触发
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
}
}
这种情况下第一次触发回调时,now - lastTime通常为0,小于delay,所以fn不会执行,看起来像是apply没有生效,实际上是节流逻辑拦截了执行。
对应的解决方法
- 返回函数使用普通函数声明,保证this是调用时的上下文,不要用箭头函数作为返回函数
- 调用apply时第二个参数直接传递args数组,不要展开参数
- 检查节流的时间判断逻辑,确保lastTime初始值合理,delay参数设置正确
- 如果需要固定上下文,可以在节流函数外层提前绑定,比如使用bind方法固定fn的this
下面是一个修正后的完整节流函数实现:
function throttle(fn, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
// 正确绑定上下文和参数
fn.apply(this, args);
lastTime = now;
}
}
}
JavaScript节流函数apply函数上下文this绑定修改时间:2026-06-25 10:18:25