2016-11-25 34 views
1

我在使用setTimeout函數內部的參數調用函數時遇到問題。基本上我試圖做一個小型的在線遊戲,在那裏我創建一個命令隊列,然後一次執行一個(每個都需要一些時間來顯示可視化)。作爲setTimeout()中的參數傳遞時,變量會丟失()

不幸的是,我似乎無法在setTimeout()中傳遞任何變量作爲參數。雖然當我調用該函數時,該變量確實存在,但它在執行後不存在。該函數不會跟蹤傳遞的值。

有沒有解決這個問題的方法?非常感謝您的幫助。下面是一個代碼我使用:

function executeCommands() { 
    var commands = document.getElementsByClassName("cmdplace"); 
    var timeout = 0; 
    for (i = 0; i < commands.length; i++) { 
     console.log(commands[i].childNodes[0]); //variable exists 
     setTimeout(function() {go(commands[i].childNodes[0]);}, timeout+=400); //Uncaught TypeError: Cannot read property 'childNodes' of undefined 
     console.log(commands[i].childNodes[0]); //variable still exists 
    } 
} 

function go(command) { 
    //do somethig based on the passed command 
} 
+2

什麼去()?.. – baao

+0

啊,對不起。 go()是我的函數,它根據傳遞的命令執行某些操作。 –

+0

@PetrHofman,你可以看到下面 – Aruna

回答

2

當你的函數被調用時,i等於commands.lengthcommands[i]undefined
他們捕獲變量i,而不是它的值。
當他們執行時,他們得到的實際值爲i,但到目前爲止它已達到commands.length(這是用於打破你的循環的條件)。

你可以做這樣的事情來解決它:

setTimeout(function(j) { 
    go(commands[j].childNodes[0]); 
}.bind(null, i), timeout+=400); 

或者這樣:

setTimeout((function(j) { 
    return function() { 
     go(commands[j].childNodes[0]); 
    }; 
})(i), timeout+=400); 

還要注意的是,當你定義它,i是一個全局變量。


正如@PMV的評論所述,現代JavaScript(如果這是您的選擇)有一種更簡單的方法。
只需使用一個let聲明,因爲它遵循:

for (let i = 0; i < commands.length; i++) { 
    // do whatever you want here with i 
} 

這將確保每次迭代得到一個名爲i新的變量,你可以捕捉它的原代碼。

+0

我的回答有一個與ES6更簡單的方法:只需使用一個'let'聲明:'的(讓我= 0;我 PMV

+0

@PMV對。我在添加評論時提及了答案。謝謝。 – skypjack

+0

@Petr hofman請閱讀https://community.risingstack.com/explaining-javascript-closure-scope-chain-examples/ –

0

您需要爲每個項目製作不同的副本。在setTimeout運行時,循環已經完成。

var timeout = 0; 
 

 
function executeCommands() { 
 
    var commands = document.getElementsByClassName("cmdplace"); 
 
    
 
    for (i = 0; i < commands.length; i++) { 
 
      go(commands[i]); 
 
    } 
 
} 
 

 
function go(command) { 
 
    setTimeout(function() { 
 
    console.log(command); 
 
    }, timeout += 400); 
 
} 
 

 
executeCommands();
<ul> 
 
    <li class="cmdplace">A</li> 
 
    <li class="cmdplace">B</li> 
 
    <li class="cmdplace">C</li> 
 
    <li class="cmdplace">D</li> 
 
</ul>

相關問題