Вы не можете использовать функции стрелок в debounce
(ну, вам нужно знать, где вы можете, а где нет)
Функция стрелки bind this
при их создании. Это означает, что this
в массиве никогда не будет и никогда не сможет измениться.
Например
'use strict';
function safeToString(v) {
return v === undefined
? 'undefined'
: v.toString();
}
function regularFunc() {
console.log('regular:', safeToString(this));
}
const arrowFunc = () => {
console.log('arrow:', safeToString(this));
};
regularFunc();
arrowFunc();
regularFunc.call("hello");
arrowFunc.call("world");
Обратите внимание, что в случае regularFunc
this
не определено, и позже мы можем переопределить его на hello
, но в случае arrowFunc
это всегда [Object Window]
Так что нет, к вашему отказу от ES6. Вот предположительно работающая версия ES6
const debounce = (callback, wait, immediate) => {
let timeout;
return (...args) => {
const callNow = immediate && !timeout
const next = () => callback(...args)
clearTimeout(timeout)
timeout = setTimeout(next, wait)
if (callNow) { next() }
}
}
Давайте проверим это
function es5Debounce(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 es6Debounce = (callback, wait, immediate) => {
let timeout;
return (...args) => {
const callNow = immediate && !timeout
const next = () => callback(...args)
clearTimeout(timeout)
timeout = setTimeout(next, wait)
if (callNow) {
next()
}
}
}
function safeToString(v) {
return v === undefined
? 'undefined'
: v.toString();
}
class Test {
constructor(name) {
this.name = name;
}
log(...args) {
console.log(
this ? this.name : 'undefined',
safeToString(this),
...args);
}
}
class ES5Test extends Test {
constructor() {
super('ES5:');
}
}
ES5Test.prototype.log = es5Debounce(ES5Test.prototype.log, 1);
class ES6Test extends Test {
constructor() {
super('ES6:');
}
}
ES6Test.prototype.log = es6Debounce(ES6Test.prototype.log, 1);
const es5Test = new ES5Test();
const es6Test = new ES6Test();
es5Test.log("hello");
es6Test.log("world");
Как вы видите, версия es6 не работает, потому что this
неверно. Если вы когда-либо используете только функции, не являющиеся членами, то es6Debounce
будет выглядеть так, как будто это работает, но как только вы используете функции-члены в обработчиках классов или событий, вы увидите, что es6Debounce
не работает, this
не установлен правильно ,
Код здесь пытается показать ошибку. ES5Class
и ES6Class
идентичны. Тест должен напечатать
ES5: [object Object] hello
ES6: [object Object] world
вместо этого печатается
ES5: [object Object] hello
undefined undefined world
В качестве другого примера давайте попробуем обработчик событий
function es5Debounce(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 es6Debounce = (callback, wait, immediate) => {
let timeout;
return (...args) => {
const callNow = immediate && !timeout
const next = () => callback(...args)
clearTimeout(timeout)
timeout = setTimeout(next, wait)
if (callNow) {
next()
}
}
}
function mousemove(e) {
console.log(this.id, e.pageX, e.pageY);
}
document.querySelector('#es5')
.addEventListener('mousemove', es5Debounce(mousemove));
document.querySelector('#es6')
.addEventListener('mousemove', es6Debounce(mousemove));
#es5, #es6 {
margin: 1em;
width: 10em;
height: 2em;
display: inline-block;
}
#es5 {
background: orange;
}
#es6 {
background: yellow;
}
<div id="es5">es5</div>
<div id="es6">es6</div>
Наведите указатель мыши на 2 области. Еще раз обратите внимание на то, что es6 ошибочен.
Независимо от того, важно ли это для вас, я понятия не имею, но исходный debounce
, который вы опубликовали явно, содержит код, чтобы заставить это дело работать.