Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用返回另一个函数的函数?_Javascript - Fatal编程技术网

Javascript 如何使用返回另一个函数的函数?

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

对于返回其他函数的函数是如何工作的,我基本上还不了解。我有下面的节流功能,我用它来确保命令不会被发送得太频繁。它已经完全从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 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);