无法将 Debounce ES5 转换为 ES6

Hyb*_*rid 5 javascript ecmascript-5 ecmascript-6 debounce

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

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

但是,在 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))
Run Code Online (Sandbox Code Playgroud)
Click both of these buttons fast and see how they react differently

<br />

<button class="es5">ES5</button>
<button class="es6">ES6</button>
Run Code Online (Sandbox Code Playgroud)

Jar*_*a X 4

这是用 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);
    };
};
Run Code Online (Sandbox Code Playgroud)

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

现在它的行为应该(几乎)与 ES5 版本相同...整个context = this事情在 ES5 版本中看起来完全奇怪,无论如何对于示例用法来说是有意义的

但是,根据评论,由于代码用于事件处理程序,this因此非常重要,它是事件目标,因此,您实际上无法返回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);
    };
};
Run Code Online (Sandbox Code Playgroud)

  • `context = this` 一点也不奇怪,`debounce` 的结果可以被分配为一个对象的方法,`context` 的记录使得这样的 debounce 方法在调用时能够有一个适当的 `this`。 (2认同)