Javascript 为什么这个去盎司函数不起作用?

Javascript 为什么这个去盎司函数不起作用?,javascript,Javascript,我试图做一个去盎司函数,我不明白为什么它不去盎司 我首先在这里创建了这个函数: const debounce=函数throttleFunctionCallsfunc,wait,immediate{ 让超时 返回=>{ const context=this 常量args=参数 const later==>{ 超时=空 if!立即函数applycontext,args } const callNow=立即&&!超时 clearTimeouttimeout timeout=setTimeOutler

我试图做一个去盎司函数,我不明白为什么它不去盎司

我首先在这里创建了这个函数:

const debounce=函数throttleFunctionCallsfunc,wait,immediate{ 让超时 返回=>{ const context=this 常量args=参数 const later==>{ 超时=空 if!立即函数applycontext,args } const callNow=立即&&!超时 clearTimeouttimeout timeout=setTimeOutler,等待 如果调用now func.applycontext,则为args } } const testFunction==>console.log'test'
setInterval=>debouncetestFunction,10000,100代码或多或少是完整的,但调用不正确。解块返回已解块的函数。您必须调用去抖动函数,而不是提供给去抖动的函数,或者多次调用去抖动本身

请注意,对于第一次调用的原始函数,对取消抖动的函数的调用必须停止超过取消抖动周期。这种逻辑可能会变得更加复杂,让呼叫时不时地通过,即使它们从未停止——但硬件去抖动电路通常不是这样工作的

下面是一个代码运行的示例:

函数去BounceFunc,等等{ 让超时 返回函数throttleFunctionCalls…args{ const context=this clearTimeouttimeout timeout=setTimeout=>func.applycontext、args、wait } } const testFunction=string=>console.log'test'+string const debouncedTestFunction=debounce testFunction,500; setTimeout debouncedTestFunction,100,第一次调用; setTimeout debouncedTestFunction,200,第二次调用; setTimeout debouncedTestFunction,300,第三次调用; //然后停一会儿
setTimeout debouncedTestFunction,900,第四次调用 代码或多或少是完整的,但调用不正确。解块返回已解块的函数。您必须调用去抖动函数,而不是提供给去抖动的函数,或者多次调用去抖动本身

请注意,对于第一次调用的原始函数,对取消抖动的函数的调用必须停止超过取消抖动周期。这种逻辑可能会变得更加复杂,让呼叫时不时地通过,即使它们从未停止——但硬件去抖动电路通常不是这样工作的

下面是一个代码运行的示例:

函数去BounceFunc,等等{ 让超时 返回函数throttleFunctionCalls…args{ const context=this clearTimeouttimeout timeout=setTimeout=>func.applycontext、args、wait } } const testFunction=string=>console.log'test'+string const debouncedTestFunction=debounce testFunction,500; setTimeout debouncedTestFunction,100,第一次调用; setTimeout debouncedTestFunction,200,第二次调用; setTimeout debouncedTestFunction,300,第三次调用; //然后停一会儿
setTimeout debouncedTestFunction,900,第四次调用 让我们看一下您的最后一个示例:

function debounce(func, wait) {
  let timeout
  return function throttleFunctionCalls(...args) {
    const context = this
    clearTimeout(timeout)
    timeout = setTimeout(() => func.apply(context, args), wait)
  }
}
您已经定义了一个函数debounce,它接受一个函数和一个等待时间并返回一个函数。到目前为止还不错

const testFunction = (value) => console.log('test: ' + value)
接下来,您定义了一个函数testFunction,它接受一个值并记录它

setInterval(() => debounce(testFunction, 1), 100)
这里有个问题。作为setInterval的第一个参数,您创建了一个新函数,该函数不接受任何参数,并返回调用testFunction上的debounce的结果。如上所述,解盎司将简单地返回一个函数。实际上,每100毫秒返回一次新函数,而不是执行日志逻辑

下面是使用箭头函数的代码的稍微精简版本:

const debounce = (func, wait) => {
    let timeout;
    return (...args) => {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
    };
};
我们将再次构造一个测试函数:

const testFunction = (value) => {
    console.log(`test: ${value}`);
};
setInterval(debouncedTest1, 200, 'foo');
这一次,我们将制作一个等待时间为1ms的测试函数的非公告版本:

const debouncedTest1 = debounce(testFunction, 1);
现在我们可以设置一个间隔来执行它。这也是向测试函数传递参数的方法之一:

const testFunction = (value) => {
    console.log(`test: ${value}`);
};
setInterval(debouncedTest1, 200, 'foo');
这将每隔200ms记录一次“foo”。从技术上讲,第一条日志消息将在setInterval调用后201ms出现:间隔为200ms,去盎司逻辑为1ms。此处不会发生去抖动,因为间隔长于去抖动等待时间

如果以另一种方式尝试,则不会输出任何内容:

const debouncedTest2 = debounce(testFunction, 200);
setInterval(debouncedTest2, 1, 'bar');
1ms后,间隔超时将尝试调用debouncedTest2。解盎司逻辑将使其在执行日志之前开始等待200ms。但1毫秒后,将触发下一个间隔超时,这将再次推回该去盎司间隔。这种情况会无限期地持续下去,您永远看不到任何消息

事实上,尝试用setInterval测试去盎司可能不是最好的方法

让我们尝试一个更人性化的等待期,并快速连续手动调用多次“去抖动”函数:

const debouncedTest3 = debounce(testFunction, 1000);

debouncedTest3('hi');
debouncedTest3('hello');
debouncedTest3('hey');
如果您尝试运行此测试,它将等待大约一秒钟,然后输出test:hey。前两个电话是thr 用去盎司逻辑来承认

在切线上,将参数传递给测试函数的另一种方法是将它们烘焙到取消抖动的函数调用中。有多种方法可以实现这一点。以下是两个例子:

const debouncedTest4 = debounce(testFunction, 1000);
const debouncedTest4WithArg = () => debouncedTest4('test arg');

debouncedTest4WithArg();
debouncedTest4WithArg();
debouncedTest4WithArg();

const debouncedTest5 = debounce(() => testFunction('test arg'), 1000);

debouncedTest5();
debouncedTest5();
debouncedTest5();

让我们看一下您的最后一个示例:

function debounce(func, wait) {
  let timeout
  return function throttleFunctionCalls(...args) {
    const context = this
    clearTimeout(timeout)
    timeout = setTimeout(() => func.apply(context, args), wait)
  }
}
您已经定义了一个函数debounce,它接受一个函数和一个等待时间并返回一个函数。到目前为止还不错

const testFunction = (value) => console.log('test: ' + value)
接下来,您定义了一个函数testFunction,它接受一个值并记录它

setInterval(() => debounce(testFunction, 1), 100)
这里有个问题。作为setInterval的第一个参数,您创建了一个新函数,该函数不接受任何参数,并返回调用testFunction上的debounce的结果。如上所述,解盎司将简单地返回一个函数。实际上,每100毫秒返回一次新函数,而不是执行日志逻辑

下面是使用箭头函数的代码的稍微精简版本:

const debounce = (func, wait) => {
    let timeout;
    return (...args) => {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
    };
};
我们将再次构造一个测试函数:

const testFunction = (value) => {
    console.log(`test: ${value}`);
};
setInterval(debouncedTest1, 200, 'foo');
这一次,我们将制作一个等待时间为1ms的测试函数的非公告版本:

const debouncedTest1 = debounce(testFunction, 1);
现在我们可以设置一个间隔来执行它。这也是向测试函数传递参数的方法之一:

const testFunction = (value) => {
    console.log(`test: ${value}`);
};
setInterval(debouncedTest1, 200, 'foo');
这将每隔200ms记录一次“foo”。从技术上讲,第一条日志消息将在setInterval调用后201ms出现:间隔为200ms,去盎司逻辑为1ms。此处不会发生去抖动,因为间隔长于去抖动等待时间

如果以另一种方式尝试,则不会输出任何内容:

const debouncedTest2 = debounce(testFunction, 200);
setInterval(debouncedTest2, 1, 'bar');
1ms后,间隔超时将尝试调用debouncedTest2。解盎司逻辑将使其在执行日志之前开始等待200ms。但1毫秒后,将触发下一个间隔超时,这将再次推回该去盎司间隔。这种情况会无限期地持续下去,您永远看不到任何消息

事实上,尝试用setInterval测试去盎司可能不是最好的方法

让我们尝试一个更人性化的等待期,并快速连续手动调用多次“去抖动”函数:

const debouncedTest3 = debounce(testFunction, 1000);

debouncedTest3('hi');
debouncedTest3('hello');
debouncedTest3('hey');
如果您尝试运行此测试,它将等待大约一秒钟,然后输出test:hey。前两个调用被去盎司逻辑丢弃

在切线上,将参数传递给测试函数的另一种方法是将它们烘焙到取消抖动的函数调用中。有多种方法可以实现这一点。以下是两个例子:

const debouncedTest4 = debounce(testFunction, 1000);
const debouncedTest4WithArg = () => debouncedTest4('test arg');

debouncedTest4WithArg();
debouncedTest4WithArg();
debouncedTest4WithArg();

const debouncedTest5 = debounce(() => testFunction('test arg'), 1000);

debouncedTest5();
debouncedTest5();
debouncedTest5();
在通话中

您将testFunction的返回值(未定义)传递给debounce,而不是函数本身,并且b从不调用debounce返回的函数。调用应该是这样的:

const debouncedTestFunction = debounce(testFunction, 10000)
setInterval(() => debouncedTestFunction(), 100)
或者简言之

setInterval(debounce(testFunction, 10000), 100)
也就是说,您误用了箭头语法。Arrow函数没有自己的and函数,而是按词汇继承它们,因此您的代码无法工作。这是必须的

function debounce(func, wait, immediate) {
  let timeout
  return function() {
//       ^^^^^^^^^^
    const later = () => {
      timeout = null
      if (!immediate) func.apply(this, arguments)
    }
    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func.apply(this, arguments)
  }
}
在通话中

您将testFunction的返回值(未定义)传递给debounce,而不是函数本身,并且b从不调用debounce返回的函数。调用应该是这样的:

const debouncedTestFunction = debounce(testFunction, 10000)
setInterval(() => debouncedTestFunction(), 100)
或者简言之

setInterval(debounce(testFunction, 10000), 100)
也就是说,您误用了箭头语法。Arrow函数没有自己的and函数,而是按词汇继承它们,因此您的代码无法工作。这是必须的

function debounce(func, wait, immediate) {
  let timeout
  return function() {
//       ^^^^^^^^^^
    const later = () => {
      timeout = null
      if (!immediate) func.apply(this, arguments)
    }
    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func.apply(this, arguments)
  }
}

调用debounce而不是将函数名作为引用传递时,您正在调用testFunction是的,我有这种感觉,但我尝试了debouncetestFunction,1000,但它仍然表现得很奇怪。谢谢,让我再试试。当我把它作为参考时,它就挂起来了。我可以帮你介绍一个卖分号键的人。你猜对了。要将任意参数传递给回调函数,让回调函数通过闭包将其拾取:debouncefunction{testfunctionmany,arguments,To,process},1000当调用debounce时,您正在调用testFunction,而不是将函数名作为引用传递是的,我有这种感觉,但我尝试了debouncetestFunction,1000,它仍然表现得很奇怪。谢谢,让我再试试。当我把它作为参考时,它就挂起来了。我可以帮你介绍一个卖分号键的人。你猜对了。要将任意参数传递给回调函数,让回调函数通过闭包拾取它们:debouncefunction{testfunctionmany,arguments,To,process},1000Ahh。。“你的意思是“不要”而不是“做”?@slebetman我想我是想把重点放在词汇上,但你是对的,这让人困惑。。“你的意思是“不要”而不是“做”?@slebetman我想我本想把重点放在词汇上,但你是对的,这让人困惑,谢谢。我真正的问题是,我没有意识到每次都只是重新启动setTimeout,所以它永远无法完成,因为我正在终止脚本。这里的所有答案都非常有用,但我很欣赏你在工作流程中所做的步骤,并提到传递参数。我制作了一个使用for循环的不同示例,现在我可以非常清楚地看到它是如何工作的,更不用说你的示例了。谢谢。我真正的问题是我没有意识到
每次只是重新启动setTimeout,所以它永远无法完成,因为我正在终止脚本。这里的所有答案都非常有用,但我很欣赏您在工作流程中所做的步骤,并提到传递参数。我制作了一个使用for循环的不同示例,现在我可以非常清楚地看到它是如何工作的,更不用提您非常清楚的示例了。感谢您的回复。签出并粘贴示例代码,您可以看到它可能是如何传输的。我会粘贴输出,但它会在评论框中看起来很恶心。谢谢你的回复。签出并粘贴示例代码,您可以看到它可能是如何传输的。我会粘贴输出,但它在评论框中看起来很粗糙。