Javascript 如何使用返回另一个函数的函数?
对于返回其他函数的函数是如何工作的,我基本上还不了解。我有下面的节流功能,我用它来确保命令不会被发送得太频繁。它已经完全从StackOverflow中删除了,这不是我写的Javascript 如何使用返回另一个函数的函数?,javascript,Javascript,对于返回其他函数的函数是如何工作的,我基本上还不了解。我有下面的节流功能,我用它来确保命令不会被发送得太频繁。它已经完全从StackOverflow中删除了,这不是我写的 // Returns a function, that, when invoked, will only be triggered at most once // during a given window of time. Normally, the throttled function will run // as muc
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
function throttle(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function () {
previous = options.leading === false ? 0 : Date.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function () {
var now = Date.now();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
};
问题是我想用这个滑块做一些非节流的事情。下面的方法不起作用
volSlider = document.querySelector("#slider-vol");
volSlider.oninput = setVolume();
function setVolume() {
return function () {
console.log(`Volume ${volSlider.value}`);
throttle(sendVolumeMessage, 100);
}
}
function sendVolumeMessage() {
console.log(`Throttled Volume ${volSlider.value}`);
}
控制台日志显示“Volume 30”或任何数字,但它不显示限制的卷。关于函数内部传递函数的工作原理,我还不了解什么?很明显,我实际上并没有在setVolume函数中调用throttle函数,但我一辈子都不知道为什么。存储throttle并调用它
volSlider = document.querySelector("#slider-vol");
volSlider.oninput = setVolume();
function setVolume() {
const fnc = throttle(sendVolumeMessage, 100);
return function () {
console.log(`Volume ${volSlider.value}`);
fnc();
}
}
function sendVolumeMessage() {
console.log(`Throttled Volume ${volSlider.value}`);
}
或者使用addEventListener添加两个单独的事件
function otherFunction () {
console.log(new Date());
}
volSlider = document.querySelector("#slider-vol");
volSlider.addEventListener('input', throttle(sendVolumeMessage, 100));
volSlider.addEventListener('input', otherFunction);
throttle
函数返回一个新函数,但您的代码从未使用该返回函数。考虑到这一点,它的工作原理如下:
const throttledSendVolumeMessage=节流(sendVolumeMessage,100);//获取函数*的限制版本一次*
volSlider=document.querySelector(“#slider vol”);
volSlider.oninput=setVolume();
函数setVolume(){
返回函数(){
log(`Volume${volSlider.value}`);
throttledSendVolumeMessage();//调用函数的已保存限制版本
}
}
函数sendVolumeMessage(){
log(`Throttled Volume${volSlider.value}`);
}
(注意:重要的是要将节流函数存储在内部函数的范围之外,以便它只调用一次节流
。否则,每次都会创建一个新的单独节流版本的函数,这不会产生任何效果,因为每个版本都会被调用一次并被丢弃,因此不会产生实际效果。)节流将永远不会发生。)
但是,在另一个函数中包装您的setVolume
是毫无用处的,它可以简化为:
const throttledSendVolumeMessage=throttle(sendVolumeMessage,100);//获取函数的限制版本*一次*
volSlider=document.querySelector(“#slider vol”);
volSlider.oninput=setVolume;//此处不再调用
函数setVolume(){//不返回其他函数
log(`Volume${volSlider.value}`);
throttledSendVolumeMessage();//调用函数的已保存限制版本
}
函数sendVolumeMessage(){
log(`Throttled Volume${volSlider.value}`);
}
但实际上,我们可以删除所有命名函数,这些函数甚至会在其定义上方被引用,并将代码缩短为:
const volSlider=document.querySelector(“#slider vol”);
const throttledSendVolumeMessage=节流(函数(){
log(`Throttled Volume${volSlider.value}`);
}, 100);
volSlider.oninput=函数(){
log(`Volume${volSlider.value}`);
throttledSendVolumeMessage();
};
最后,您可以消除外部范围中对volSlider
变量的依赖:
const throttledSendVolumeMessage=节流(函数(volSlider)){
log(`Throttled Volume${volSlider.value}`);
}, 100);
document.querySelector(“#slider vol”).oninput=function(){
log(`Volume${this.value}`);
throttledSendVolumeMessage(此);
};
另一方面,尽管这不会影响您当前的问题:通常更倾向于使用
element.addEventListener('xyz',handler)
而不是element.onxyz=handler
,因为后者只允许分配一个处理程序(并且新的分配将取代以前的分配),因此,如果您(或某些写得不好的第三方代码)的尝试将第二个侦听器附加到同一事件以执行其他操作。oninput
似乎是这里的问题。它只能接受一个处理程序。如果尝试添加另一个处理程序,则会丢弃前一个处理程序。但代码中只有一个这样的分配。是的,我第一次尝试仅使用两个oninput处理程序和I d这就是我所说的节流功能和非节流功能。我不认为只使用AdvestTeleNever代替OnPosits,我想这也会起作用。不过我觉得我对ChelyDT写的更满意。谢谢,这正是WHA。t我不知道。我不明白我实际上并没有调用油门功能,只是定义了它。感谢你提供了难以置信的详细答案。我现在已经用你和epascarello的答案解决了这个问题,现在我正在深入研究你的其他建议,以进一步清理它。
function otherFunction () {
console.log(new Date());
}
volSlider = document.querySelector("#slider-vol");
volSlider.addEventListener('input', throttle(sendVolumeMessage, 100));
volSlider.addEventListener('input', otherFunction);