問題描述
我有一個約 50 個項目的數組,在 javascript 中,它通過這個數組來檢查一個條件,如果滿足條件,它會為要檢查的復選框設置屬性.它通過得很好,但每次只更改數組中的最后一項.這是一段代碼.
I have an array of ~50 items and in javascript it goes through this array to check a condition and if the condition is met it setsattribute for checkboxes on the be checked. It goes through nicely but only changes the very final item in the array every time. Here is a section of the code.
for (i = 0; i < urlArray.length; i++) {
var newImg = new Image();
var coName = companyArray[i];
newImg.onload = function(){
if (condition is met){
nStar++;
document.getElementById(coName).setAttribute("checked", "checked");
document.getElementById(coName).checked = true;
} else {
nStar++;
document.getElementById(coName).setAttribute("checked", "checked");
document.getElementById(coName).checked = true;
document.getElementById(coName).setAttribute("disabled", "disabled");
document.getElementById(coName).disabled = true;
}
};
所以你可以看到條件是否滿足,它仍然會改變屬性,但我收到的錯誤是它只改變了數組中的最后一項.有什么想法嗎?
So as you can see if the condition is met or not it will still change the attributes but the error I have been receiving is that it only changes the final item in the array. Any ideas?
推薦答案
這是 Javascript 中異步回調的經典問題.onload 處理程序將在一段時間后調用,在 for 循環完成很久之后,因此 for 循環中的索引被固定在它結束的末尾,并且局部變量 newImg 和 coName 將只有它們在循環中的最后一個值.
This is a classic issue with an asynchronous callback in Javascript. The onload handler will be called some time later, long after the for loop has finished, thus the index in the for loop is pegged at the end where it ended up and the local variables newImg and coName will only have their last values in the loop.
您希望在 onload 處理程序中使用的任何變量都必須傳遞到實際的函數閉包中,以便它們對每個不同的 onload 處理程序都是唯一可用的.有幾種方法可以做到這一點.
Any variables that you wish to use inside the onload handler will have to passed into the actual function closure so that they are uniquely available for each different onload handler. There are several ways to do that.
這種方式使用函數閉包來捕獲傳入的值并使其可用于 onload 函數處理程序:
This way uses a function closure to capture the passed in value and make it available to the onload function handler:
for (i = 0; i < urlArray.length; i++) {
var newImg = new Image();
var coName = companyArray[i];
newImg.onload = (function (coName) {
return function(){
if (condition is met){
nStar++;
document.getElementById(coName).setAttribute("checked", "checked");
document.getElementById(coName).checked = true;
} else {
nStar++;
document.getElementById(coName).setAttribute("checked", "checked");
document.getElementById(coName).checked = true;
document.getElementById(coName).setAttribute("disabled", "disabled");
document.getElementById(coName).disabled = true;
}
};
}) (coName);
}
在 Javascript 語言中,此方法的作用是將執行匿名函數調用的返回值分配給 onload 屬性.該匿名函數調用將 coName 參數傳遞給它.該函數返回另一個匿名函數,該函數被分配為 onload 處理程序.但是,由于函數閉包在 javascript 中的工作方式,coName 的值被捕獲在函數閉包中,并且在函數閉包期間保持可供 onload 處理程序訪問.可以把它想象成一個函數的實例,它周圍有狀態(局部變量的值),每次設置時都會被唯一地捕獲.在這種情況下,它會捕獲 coName 變量的值并將其放入閉包中,在該閉包中它變得唯一,并且不會受到后續對 for 循環中外部 coName 變量的更改的影響.
In Javascript-speak, what this method does is assign to the onload attribute the return value from executing an anonymous function call. That anonymous function call passed the coName parameter into it. That function returns another anonymous function which is what gets assigned as the onload handler. But, because of the way function closures work in javascript, the value of coName is captured in the function closure and is kept accessible to the onload handler for the duration of the function closure. One can think of it a little like an instance of a function with state around it (values of local variables) that is uniquely capture each time it's set up. In this case, it captures the value of the coName variable and puts it into the closure where it becomes unique and won't be effected by later changes to the outer coName variable that's in the for loop.
另一種方法是將參數放在實際對象上,以便您可以從那里檢索它:
Another way to do it is to put the parameter on the actual object so you can retrieve it from there:
for (i = 0; i < urlArray.length; i++) {
var newImg = new Image();
newImg.setAttribute("coName". companyArray[i]);
newImg.onload = function() {
var coName = this.getAttribute("coName");
if (condition is met){
nStar++;
document.getElementById(coName).setAttribute("checked", "checked");
document.getElementById(coName).checked = true;
} else {
nStar++;
document.getElementById(coName).setAttribute("checked", "checked");
document.getElementById(coName).checked = true;
document.getElementById(coName).setAttribute("disabled", "disabled");
document.getElementById(coName).disabled = true;
}
};
}
這篇關于Javascript 僅設置數組中最后一項的屬性的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!