【问题标题】:JS Recursive function callJS递归函数调用
【发布时间】:2016-08-01 13:21:33
【问题描述】:

如果我像这样调用函数once

var button = document.querySelector('button');

button.addEventListener('click', once);

function once() {
  console.log('one');

  button.removeEventListener('click', once);
}

它只调用一次。

但是如果我这样打电话once()

var button = document.querySelector('button');

button.addEventListener('click', once());

function once() {
  console.log('one');

  button.removeEventListener('click', once());
}

异常抛出

异常:内部错误:递归过多

请您解释一下为什么会这样。

【问题讨论】:

  • 你会立即调用一个带有()的函数
  • 如果在函数名后使用(),则执行该函数。而且你不想在传递给addEventListenerremoveEventListener之类的方法时被执行,所以只需将其删除。
  • 哈哈,我喜欢它抛出的异常——“递归过多”
  • 我想说“堆栈溢出”太陈词滥调了? :)

标签: javascript recursion


【解决方案1】:

() 在函数名之后调用函数。所以button.addEventListener('click', once()); 绑定了once() 方法的返回值,这是未定义的。

由于once() 是在没有任何中断语句的情况下递归调用的,因此您将得到InternalError: too much recursion

你应该传递函数引用。

button.addEventListener('click', once); 

更多信息:

Pointer Vs Delegates

【讨论】:

【解决方案2】:

如果您将() 放在包含函数的变量名称之后,则您调用该函数

如果一个函数调用自己,那么它将被调用,调用自己,再次调用自己,等等直到无穷大。这是递归。做无穷大的事情会导致计算机内存不足,所以这是不可取的。

JavaScript 引擎会在您尝试时抛出异常来防止这种情况发生。

(当然也有例外,有条件地调用自己的函数可以是very useful)。

【讨论】:

    【解决方案3】:

    第一个代码是正确的,因为你注册了要调用的函数。

    第二个代码尝试注册函数调用once() 的结果。这意味着当您只想注册该功能时,您实际上会执行该功能。现在,在您的函数体中,您执行相同的操作来取消注册回调。在这里,你调用了你已经在执行的函数,因此你无限递归。

    【讨论】:

      猜你喜欢
      • 2019-01-19
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多