谁能用这个例子向我解释为什么 JSLint 提示“循环内的函数”:
for (var i = 0; i < buttons.length; i++) {
(function(i) {
buttons[i].onclick = function(e) {
t.progressBars[t.current].update(buttons[i].getAttribute("data-value"));
}
})(i);
}
但是当我把它改成:
function makeHandler(i)
{
return function() {
t.progressBars[t.current].update(buttons[i].getAttribute("data-value"));
}
}
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = makeHandler(i);
}
我不太明白,因为似乎每次循环迭代都必须返回新的函数对象,即使它发生在 makeHandler()
函数内部。为什么第二个示例适用于 JS linters?
最佳答案
引自linterrors ,
var elems = document.getElementsByClassName("myClass"), i; for (i = 0; i < elems.length; i++) { (function (iCopy) { "use strict"; elems[i].addEventListener("click", function () { this.innerHTML = iCopy; }); }(i)); }
What we have now captures the value of
i
at each iteration of the loop. This happens because JavaScript passes arguments to functions by value. This means thatiCopy
within the capturing function is not related to i in any way (except for the fact that they happen to have the same value at that point in time). Ifi
changes later (which it does - on the next iteration of the loop) theniCopy
is not affected.This will work as we expect it to but the problem now is that the JavaScript interpreter will create an instance of the capturing function per loop iteration. It has to do this because it doesn't know if the function object will be modified elsewhere. Since functions are standard JavaScript objects, they can have properties like any other object, which could be changed in the loop. Thus by creating the function in the loop context, you cause the interpreter to create multiple function instances, which can cause unexpected behavior and performance problems. To fix the issue, we need to move the function out of the loop:
我希望在这里使用 Array.prototype.forEach
,就像这样
buttons.forEach(function(curButton) {
curButton.onclick = function(e) {
t.progressBars[t.current].update(curButton.getAttribute("data-value"));
};
});
关于循环内的 JavaScript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26154150/