2011-06-08 173 views
1

嗨,我有一个递归问题。递归函数未定义错误

我跟着这个例子从wc3 http://www.w3schools.com/jsref/met_win_settimeout.asp 但我的似乎根本不工作。

function rotateImages(start) 
    { 
    var a = new Array("image1.jpg","image2.jpg","image3.jpg", "image4.jpg"); 
    var c = new Array("url1", "url2", "url3", "url4"); 
    var b = document.getElementById('rotating1'); 
    var d = document.getElementById('imageurl'); 
    if(start>=a.length) 
     start=0; 
    b.src = a[start]; 
    d.href = c[start]; 
    window.setTimeout("rotateImages(" + (start+1) + ")",3000); 
    } 

    rotateImages(0); 

萤火引发错误:

rotateImages is not defined 
[Break On This Error] window.setTimeout('rotateImages('+(start+1)+')',3000); 

但是,如果我改变超时:

window.setTimeout(rotateImages(start+1),3000); 

它recursives但不知何故迟迟不工作,给了我太多的递归(7000秒)

+0

W3Schools的**不是**的W3C。他们是一个低质量,广告覆盖,良好的SEO第三方教程网站。 – Quentin 2011-06-08 18:55:40

+0

您推荐的任何好网站? – hamahama 2011-06-09 00:59:41

回答

0

请注意W3School的代码。

其他答案给出了一个解决方案。我只是补充说,每次调用rotateImages函数时,都会重新创建阵列并重复DOM选择。这是不必要的。

你可以改变你的代码是这样的:

(function() { 
    var a = ["image1.jpg","image2.jpg","image3.jpg", "image4.jpg"]; 
    var c = ["url1", "url2", "url3", "url4"]; 
    var b = document.getElementById('rotating1'); 
    var d = document.getElementById('imageurl'); 

    function rotateImages(start) { 
     b.src = a[start]; 
     d.href = c[start]; 
     window.setTimeout(function() { 
      rotateImages(++start % a.length); 
     }, 3000); 
    } 

    rotateImages(0); 
})(); 
+0

现场示例:http://jsfiddle.net/f3wFt/ – user113716 2011-06-08 19:06:03

+0

感谢您的答案并帮助重构我的代码! – hamahama 2011-06-09 00:54:23

+0

我爱这行! ++ start%a.length – hamahama 2011-06-09 01:02:54

1

试试这个语法:

window.setTimeout(function() { 
    rotateImages(start+1); 
},3000); 

setTimeout()需要函数引用作为第1个参数。简单地把函数调用放在那里会给te函数的返回值作为参数,这就是延迟不起作用的原因。然而,你首先尝试评估一个字符串是一个好方法,但不推荐。

+0

现在我明白了..我怎么知道什么时候应该调用函数? – hamahama 2011-06-09 00:56:46

+0

如果你需要你函数的返回值。如果你想给你的函数(稍后调用它),你应该使用函数引用(不带大括号)或匿名函数。 – aorcsik 2011-06-09 09:08:31

3

为什么要避免eval有很多原因,它打破范围就是其中之一。将一个字符串传递给setTimeout会在定时器耗尽时导致该值为eval

您应该改为传递一个函数。

window.setTimeout(rotateImages(start+1),3000); 

这立即调用rotateImages,然后将它的返回值setTimeout。这没有帮助,因为rotateImages没有返回函数。

你可能想:

window.setTimeout(rotateImages,3000,[start+1]); 

,或者创建环绕开始封闭匿名函数和传递,而不是:

window.setTimeout(function() { rotateImages(start + 1); },3000); 

后一种选择具有浏览器之间提供更好的支持。

+0

第二种方法不适用于Internet Explorer,因此最后一种方法是首选(或使用定义的功能)。 HTTP://blog.skinkers。com/2011/05/31/fixing-internet-explorers-settimeout-setinterval-scoping-issues-and-overcome-apisframeworks-that-dont-allow-arguments-to-be-pass-to-callback-methods/has a如何处理它的好写法(使用函数返回函数) – 2011-06-08 18:52:42

+0

谢谢..我会去读更多关于eval – hamahama 2011-06-09 00:59:31

+0

所有你需要知道的关于eval的是你不应该使用它。它拧紧了范围。它很慢。这很难调试。它可能会引入安全问题。使用我答案中的最后一个例子。 – Quentin 2011-06-09 06:32:17