2013-07-21 142 views
0

我的問題很簡單。我使用的是內部的for循環的setTimeout,運行時 錯誤過程中產生曰:setTimeout產生範圍錯誤

Uncaught TypeError: Cannot call method 'setAttribute' of undefined 

我用JavaScript的經驗是超薄(我跳過的jQuery學習的緣故) ,我以爲這有用我打電話給setTimeout的方式。

看看我的功能,我想知道爲什麼「元素」不是從匿名函數內部可用。

function hide_visable_elements() 
{ 
    // remove body EventListener 
    var body = document.getElementsByTagName("body"); 
    body[0].removeEventListener("click", hide_visable_elements, true); 

    var elements = document.getElementsByClassName("visible"); 
    for (var i = 0; i < elements.length; ++i) 
    { 
    elements[i].removeAttribute("class"); 
    setTimeout(function() { elements[i].setAttribute("class", "hidden") }, 300); 
    } 
} 
+1

您推遲的函數在循環完成後執行很長時間,此時'i === elements.length'和'elements [i]'當然是'undefined',因爲它超出了邊界的訪問範圍。 – Esailija

+0

那我該如何達到所需的延遲呢?根據你所說的話,如果我將300ms改爲0ms,它應該可以工作,但不是。 –

+0

在你推遲一個函數之前,在那個時候捕獲'i'的值,這樣當函數最終執行時,它將使用你捕獲的值而不是當前的任何'i'。這與毫秒數毫無關係,任何數量都會在循環執行後長時間執行。 – Esailija

回答

1

下面是使被執行時,它的循環完成後,你如何能捕捉迭代的電流值爲例(它總是後,由於異步性質),它會做正確的事:

function setHidden(element) { 
    return function() { 
     element.setAttribute("class", "hidden"); 
    }; 
} 

function hide_visable_elements() { 
    // remove body EventListener 
    var body = document.getElementsByTagName("body"); 
    body[0].removeEventListener("click", hide_visable_elements, true); 
    var elements = document.getElementsByClassName("visible"); 
    for (var i = 0; i < elements.length; ++i) { 
     elements[i].removeAttribute("class"); 
     setTimeout(setHidden(elements[i]), 300); 
    } 
} 


順便說一下我使用的描述比較,時間t的最小量「後長」帽子在延遲功能可能執行之前經過的時間爲4或13毫秒,但循環執行時間以微秒或納秒爲單位進行測量。

+0

這種方式產生相同的錯誤.. –

+0

@ elad.chen確保你清除緩存,這裏的工作演示http://jsfiddle.net/7yWWz/1/ – Esailija

+0

這很奇怪,我使用完全相同的代碼小提琴,它不起作用。 Chrome與之前報告的錯誤相同。 (緩存被清除)。任何想法我在這裏想念什麼? –