函数调用自身不起作用(无限循环,Javascript)

16 浏览
0 Comments

函数调用自身不起作用(无限循环,Javascript)

我试图等待并在数组中的所有图像加载完成后(使用.complete),根据这个答案here,然后得到一条消息。为此,我设置了一个无限循环,如下所示。然而,当我运行这段代码时,会出现一个错误,提示checkForAllImagesLoaded()没有定义。这段代码通过一个书签脚本运行,因此它被封装在一个匿名函数结构中(如下所示)。如果我在那个结构之外重新定义我的函数和变量,它就能工作。但是这似乎是一种不好的书签脚本编写方式。我该如何修复这个问题,让它在setTimeout之后仍然能够识别函数?

0
0 Comments

问题的原因是在代码中设置了每次调用时的超时时间。解决方法是只在每次调用 checkForAllImagesLoaded() 时设置一次超时时间,并且可能需要增加等待时间(20 毫秒太快了)。以下是修改后的代码:

function checkForAllImagesLoaded() {
  var allComplete = true;
  var i = 0;
  while (i < images.length && allComplete) {
    allComplete = images[i++].complete;
  }
  if (!allComplete) { // 有未加载完成的图片吗?
    setTimeout(checkForAllImagesLoaded, 1000); // 等待一秒钟!
  }
}

在这段修改后的代码中,我们只在每次调用 checkForAllImagesLoaded() 时设置了一次超时时间,并且将超时函数的参数直接传递为函数名,而不是字符串形式。这样可以保证函数自身的调用正常工作,避免了无限循环的问题。另外,我们将超时时间增加到了 1000 毫秒,以便给图片加载更多的时间。

这样,问题就得到了解决。

0
0 Comments

当函数调用自身时无法工作(无限循环,Javascript)的问题出现的原因是在setTimeout调用中去掉了()。

解决方法是将()添加回setTimeout调用中。这是因为如果不添加(),浏览器会尝试在全局作用域中执行类似于eval('checkForAllImagesLoaded')的代码,而在全局作用域中没有定义checkForAllImagesLoaded这个名称。

正确的代码应该是:

setTimeout('checkForAllImagesLoaded()', 20);

这样,checkForAllImagesLoaded函数将会以每20毫秒的间隔被调用一次,直到满足某个条件跳出循环。

0
0 Comments

问题的原因是在setTimeout函数中传入了一个字符串而不是直接引用函数,导致函数无法正常调用。解决方法是将setTimeout的第一个参数改为直接引用函数。

在setTimeout函数中,如果将函数名放在引号中,如"checkForAllImagesLoaded"或"checkForAllImagesLoaded()",那么setTimeout会在延时结束时执行传入的代码。此时,setTimeout会在全局对象(window)中搜索checkForAllImagesLoaded函数,但是由于该函数并没有在全局对象中定义,所以会出现undefined错误。

在你的代码中,checkForAllImagesLoaded函数是包裹在一个自调用匿名函数中的,因此在函数外部是无法访问到checkForAllImagesLoaded的。所以,在setTimeout的调用中,应该传入一个直接引用函数而不是字符串。

解决方法是将setTimeout的第一个参数改为直接引用函数,如下所示:

setTimeout(checkForAllImagesLoaded, 20);

setTimeout函数可以接受一个函数作为参数(可选的还可以传入参数),或者接受一个包含JavaScript代码的字符串作为参数。具体用法如下:

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

var timeoutID = window.setTimeout(code, delay);

0