2015-08-26 189 views
2

我有以下功能登錄通過在某一給定時間的函數是句子中的人物,看看下面的功能:For循環不允許的setTimeout執行

function print_string(param , timer) { 

    var strt_point = 0, 
     str_len = param.length, 
     self = this; 


    //typewritter(); 

    typeit(); 

    function typeit() { 

    setTimeout(function(){ 

     console.log(param.substring(strt_point).charAt(0)); 

     if(strt_point < str_len) { 
     strt_point++; 
     typeit() 
     } 
    } , timer); 
    } 

} 

var str = print_string("hey there , whats up , hows the weather in Manhatten" , 50); 
console.log(str); 

以上程序員工作正常,現在如果我添加一個for循環到上面的程序IE 包裹的setTimeout在for循環中,

function print_string(param , timer) { 

    var strt_point = 0, 
     str_len = param.length, 
     self = this; 

    for(var i = 0 ; i < str_len ; i++) { 

    //typewritter(); 

    typeit(); 

    function typeit() { 

    setTimeout(function(){ 

     console.log(param.substring(strt_point).charAt(0)); 

     if(strt_point < str_len) { 
     strt_point++; 
     typeit() 
     } 
    } , timer); 
    } 

} 

var str = print_string("hey there , whats up , hows the weather in Manhatten" , 50); 
console.log(str); 

所有的人物在一次打印,爲什麼呢?

爲什麼for循環不符合setTimeout間隔?有人可以解釋嗎?

+3

你有一個函數,這是不允許的內部函數,函數typeit是內部功能print_string –

+0

豈不等於說他們調用關閉?任何文件來證明你的話是什麼?我是一個JS新手,所以不是專家本人! –

+2

這真是毫無根據的@BhawinParkeria – charlietfl

回答

2

如果你想timer參數充當的實際間隔,使用此:

function print_string(param, timer) { 

    for(var i = 0 ; i < param.length ; i++) { 

    setTimeout((function(char){ 

     return function() { 

     console.log(char); 

     } 

    })(param.charAt(i)), timer * i); 
    } 
} 

var str = print_string("hey there , whats up , hows the weather in Manhatten" , 500); 

這裏是一個fiddle

您的困惑是for循環立即發生,或者與處理器允許的速度一樣快。當setTimeout處理程序執行時,它與您可能期望的範圍有不同的範圍。作用域不再位於for循環內(因爲發生在處理器的不同勾號中),因此打印變量丟失。爲了解決這個問題,我使用了所謂的閉包。我正在建立一個函數,打印我需要的特定變量,並將它作爲參數傳遞給setTimeout

瞭解更多關於closures here

+0

這也具有相同的效果,一次打印出所有字符:(而不是間隔打印字符! –

+1

循環在瞬間完成...創建多個調用功能,它將同時觸發 – charlietfl

+0

@Tenali_raman請參閱修訂後的答案。有一個示例小提琴和一個解釋。 – shennan

0

這兩段代碼的區別是:
第一次您在每次觸發超時功能時設置定時器。
在第二種情況下,您在每個「foreach」迭代中同時(幾乎)設置所有定時器,以便同時觸發事件。
您可以通過timer + = 50來防止它。

0

我會盡力應歸結爲:

你傳遞一個字符串30個字符的功能print_string,使for循環將迭代和調用setTimeout 30倍。 50ms後,第一個setTimeout回調將被調用,並將輸出字符串的第一個字符。變量strt_point將遞增。然後第二個for循環迭代的第二個setTimeout回調將立即調用,並且由於strt_point已被增加,第二個字符將被打印。

問題是,對於for循環的所有迭代,您都有一個變量strt_point,以便所有字符在50ms後打印。

0

我想你想是這樣的:

var print_string = function (param, interval) { 
 
    var 
 
    i = 0, 
 
    len = param.length, 
 
    
 
    result = document.getElementById('result'), 
 
    
 
    // function called for every characters 
 
    next = function() { 
 
     // get the current character 
 
     var char = param.charAt(i); 
 
     
 
     // do what you want with them 
 
     result.innerHTML += char; 
 
     
 
     // if not the end of the string 
 
     if (++i < len) { 
 
     // continue after the interval 
 
     setTimeout(next, interval); 
 
     } 
 
    } 
 

 
    next(); 
 
} 
 

 
print_string('hey there , whats up , hows the weather in Manhatten!', 50);
<div id="result"></div>