javascript - 无法将 Debounce ES5 转换为 ES6

标签 javascript ecmascript-6 ecmascript-5 debouncing

我在网上找到了一个很棒的debounce() 函数代码,但是我很难将它从 ES5 转换为 ES6。

问题如下:当我使用 ES5 实现时,一切正常。调整窗口大小,console.log() 立即 被触发,随后的大小调整将被忽略,直到我指定的 500 毫秒之后。

然而,在 ES6 实现中,第一次调用会立即生效...但之后的每次调用都会延迟 500 毫秒,即使在冷却之后也是如此!

如果有人知道我做错了什么,我将不胜感激。

例子:

function debounceES5(func, wait, immediate) {
    var timeout;
    return function () {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

const debounceES6 = (callback, wait, immediate=false) => {
  let timeout = null
  return (...args) => {
    const callNow = immediate && !timeout
    const next = () => callback(...args)
    clearTimeout(timeout)
    timeout = setTimeout(next, wait)
    if (callNow) { next() }
  }
}

document.querySelector('.es5').addEventListener('click', debounceES5(() => {console.log('clicked')}, 1000, true))

document.querySelector('.es6').addEventListener('click', debounceES6(() => {console.log('clicked')}, 1000, true))
Click both of these buttons fast and see how they react differently

<br />

<button class="es5">ES5</button>
<button class="es6">ES6</button>

最佳答案

这是用 ES6 编写的 ES5 函数 - 没有跳过任何细节(不相关的 context 除外)

const debounce = (func, wait, immediate=false) => {
    let timeout;
    return (...args) => {
        const later = () => {
            timeout = null; // added this to set same behaviour as ES5
            if (!immediate) func(...args); // this is called conditionally, just like in the ES5 version
        };
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func(...args);
    };
};

请注意,later 函数的作用与 ES5 版本完全相同

这现在应该(几乎)与 ES5 版本的行为相同......整个 context = this 事情 在 ES5 版本中似乎完全奇怪 对示例有意义用法

However, as per comments, since the code is used for event handler, this is quite important, it's the Event Target so, you really can't return an arrow function

更好的代码应该是

const debounce = (func, wait, immediate=false) => {
    let timeout;
    return function (...args) {
        const later = () => {
            timeout = null; // added this to set same behaviour as ES5
            if (!immediate) func.apply(this, args); // this is called conditionally, just like in the ES5 version
        };
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(this, args);
    };
};

关于javascript - 无法将 Debounce ES5 转换为 ES6,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56013445/

相关文章:

javascript - 在 React 中调用外部 JS

javascript - 追加时出现"undefined"错误?

javascript - 从 package.json 运行 Node.js 命令

javascript - Babel 已经做了 Object.create(superClass.prototype) 为什么还要用 setPrototypeOf 来继承?

javascript - 仅执行一次某些基类方法调用而不是该类的每个实例?

javascript - Babel 是编译器还是转译器?

javascript - 如何在 ECMAScript 5 中拥有 block 作用域

javascript - es5-shim 和 underscore.js?

JavaScript 在迭代数组时等待后端响应

javascript - 在 If 语句条件 Javascript/jQuery 中嵌入 For 循环