js 函数节流 event 对象传递问题

发布于 2022-09-05 20:35:18 字数 1175 浏览 19 评论 0

场景:需要绑定 keydown 事件,根据 event.keyCode 来判断是哪个键被按下,做出相应处理;但是不希望用户过于频繁的按键操作,所以用到函数节流,但是 event 对象传递过程中出现一些奇怪的现象,求大佬们解答

以下是部分代码:

// 事件绑定
window.addEventListener('keydown', throttle(keydownHandler, 50, 100, event));

// 函数节流
function throttle(fn, delay, atLeast) {
    var timeout = null,
        startTime = Date.now(),
        args = Array.prototype.slice.call(arguments, 3);

    return function () {
        var endTime = Date.now();
        clearTimeout(timeout);

        if(endTime - startTime >= atLeast) {
            fn.apply(null, args);
            startTime = endTime;
        } else {
            timeout = setTimeout(function() {
                fn.apply(null, args);
            }, delay);
        }
    };
}

// keydown 事件处理程序
function keydownHandler(event) {
    var e = event || window.event;
    var keyCode = e.keyCode || e.which;
    
    switch (keyCode) {
        /*...*/
    }
}

然而我在 keydownHandler 中打印 event 得到的结果却是这样的:
图片描述

事件类型却变成了 load ,求大佬们指点,为什么 event 对象会改变?这里的 event 对象该如何传递呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只为守护你 2022-09-12 20:35:19

你这个监听函数写得有问题
传给 throttle 函数的 event 参数为当前全局的事件对象(可能为 undefined,也可能是其他事件,取决于你调用的环境),所以造成传给 keydownHandlerevent 也始终是全局的事件对象。
当你触发键盘事件的时候,如果之前传递的全局事件对象为 undefined,则 keydownHandler 内部始终通过 window.event 来获取事件对象,而由于 setTimeout 的异步效果,当函数被调用的时候,事件对象已经被回收,所以获取 keyCode 属性会显示异常。
如果之前传递的全局事件对象为确实存在,则在 keydownHandler 内打印 event 得到的就是之前传递过来的全局事件对象。
编辑

// 事件绑定
window.addEventListener('keydown', throttle(keydownHandler, 50, 100));

// 函数节流
function throttle(fn, delay, atLeast) {
    var timeout = null,
        startTime = Date.now();

    return function (event) {
        var endTime = Date.now();
        clearTimeout(timeout);

        if(endTime - startTime >= atLeast) {
            fn.call(null, event);
            startTime = endTime;
        } else {

            timeout = setTimeout(function() {
                fn.call(null, event);
            }, delay);
        }
    };
}

// keydown 事件处理程序
function keydownHandler(event) {
    var e = event || window.event;
    var keyCode = e.keyCode || e.which;
    
    switch (keyCode) {
        /*...*/
    }
}
三寸金莲 2022-09-12 20:35:19

我这边运行正常,你这段代码是在什么环境下运行的,我的运行结果如下:
图片描述

楼下的方案不错,我这个可能烦一些

// 函数节流
function throttle(fn, delay, atLeast) {
    var timeout = null,
        startTime = Date.now(),
        args = Array.prototype.slice.call(arguments, 3);

    return function () {
        var endTime = Date.now();
        clearTimeout(timeout);

        if(endTime - startTime >= atLeast) {
            fn.apply(null, args);
            startTime = endTime;
        } else {
            timeout = setTimeout(function() {
                fn.apply(null, args);
            }, delay);
        }
    };
}

function keydownHandler(e) {
  console.log(e);
}

// keydown 事件处理程序Wrapper
function keydownHandlerWrapper(event) {
  const e = event || window.event;
  return throttle(keydownHandler, 50, 100, e);
}

window.addEventListener('keydown', function(e) {const f = keydownHandlerWrapper(e); f();});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文