[英]How to pass variable to anonymous function
我想傳遞變量setTimeout
函數並用它做一些事情。 當我警告i
值時,它會顯示我沒有預料到的數字。 我做錯了什么? 我想要從 1 到 8 的日志值。
var end=8;
for (var i = 1; i < end; i ++) {
setTimeout(function (i) {
console.log(i);
}, 800);
}
解決這個問題的標准方法是使用工廠函數:
var end=8;
for (var i = 1; i < end; i ++) {
setTimeout(makeResponder(i), 800);
}
function makeResponder(index) {
return function () {
console.log(index);
};
}
在那里,我們在循環中調用makeResponder
,它返回一個函數,該函數關閉傳遞給它的參數( index
)而不是i
變量。 (這很重要。如果您只是從匿名函數中刪除i
參數,您的代碼將部分工作,但所有函數都會看到i
在它們運行時的值,而不是最初計划時;在您的示例中,他們都會看到8
。)
更新來自您下面的評論:
...如果我這樣稱呼它會正確嗎?
setTimeout(makeResponder(i),i*800);
?
是的,如果您的目標是讓每個調用比上一個調用晚大約 800 毫秒,那將起作用:
我試過
setTimeout(makeResponder(i),setInterval(i));function setInterval(index) { console.log(index*800); return index*800; }
setTimeout(makeResponder(i),setInterval(i));function setInterval(index) { console.log(index*800); return index*800; }
setTimeout(makeResponder(i),setInterval(i));function setInterval(index) { console.log(index*800); return index*800; }
但它不能正常工作
您不會那樣使用setInterval
,並且可能根本不想為此使用它。
進一步更新:您在下面說過:
我需要第一次迭代打印 8 延遲 8 秒,第二次迭代打印 7 延遲 7 秒 ........打印 2 延遲 2 秒 ...打印 0 延遲 0 秒。
您只需再次應用上述原則,使用第二次超時:
var end=8;
for (var i = 1; i < end; i ++) {
setTimeout(makeResponder(i), i * 800);
}
function makeResponder(index) {
return function () {
var thisStart = new Date();
console.log("index = " + index + ", first function triggered");
setTimeout(function() {
console.log("index = " +
index +
", second function triggered after a further " +
(new Date() - thisStart) +
"ms delay");
}, index * 1000);
};
}
我認為您現在擁有推進這項工作所需的所有工具。
你的問題是你在一段時間后當你的setTimeout()
函數觸發時你引用了變量i
到那時, i
的值已經改變(它已經到了for
循環的末尾。為了讓每個 setTimeout 保持適當的值對於i
,您必須為每個setTimeout()
回調分別捕獲該值i
。
使用工廠函數的前一個答案做得很好,但我發現自執行函數比工廠函數更容易鍵入和遵循,但兩者都可以工作,因為兩者都在閉包中捕獲您想要的變量,因此您可以引用它們的靜態值在 setTimeout 回調中。
以下是自執行函數如何解決這個問題:
var end=8;
for (var i = 1; i < end; i ++) {
(function (index) {
setTimeout(function() {
console.log(index);
}, 800);
})(i);
}
要與i
的值成比例地設置超時延遲,您可以這樣做:
var end=8;
for (var i = 1; i < end; i ++) {
(function (index) {
setTimeout(function() {
console.log(index);
}, index * 800);
})(i);
}
自執行函數被傳遞i
的值,並且包含該值的函數內部的參數被命名為index
因此您可以引用index
以使用適當的值。
在 ES6 中使用 let
使用JavaScript的ES6(2015年發布),您可以使用let
您for
循環,它會創建一個新的,獨立的變量的每個迭代for
循環。 這是一種更“現代”的方法來解決這樣的問題:
const end = 8;
for (let i = 1; i < end; i++) { // use "let" in this line
setTimeout(function() {
console.log(i);
}, 800);
}
這不起作用的主要原因是因為setTimeout
設置為在800
之后運行以及i
的范圍。
到它執行時, i
的值已經改變了。 因此,無法收到確定的結果。 正如 TJ 所說,解決這個問題的方法是通過處理程序函數。
function handler( var1) {
return function() {
console.log(var1);
}
}
var end = 8;
for (var i = 1; i < end; i++) {
setTimeout(handler(i), 800);
}
setTimeout
接受變量作為附加參數:
setTimeout(function(a, b, c) {
console.log(a, b, c);
}, 1000, 'a', 'b', 'c');
來源。
編輯:在您的示例中, i
的有效值可能是8
,因為該函數僅在循環完成后才被調用。 您需要為每次調用傳遞i
的當前值:
var end=8;
for (var i = 1; i < end; i ++) {
setTimeout(function (i) {
console.log(i);
}, 800, i);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.