这是一个简单的JS循环不按预期运行的情况的示例,因为循环变量不在单独的范围内.
经常提出的解决方案是构造一个令人不愉快的循环代码,如下所示:
for (var i in obj) {
(function() {
... obj[i] ...
// this new shadowed i here is now no longer getting changed by for loop
})(i);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,这可以改进吗?我可以用这个:
Object.prototype.each = function (f) {
for (var i in this) {
f(i,this[i]);
}
};
// leading to this somewhat more straightforward invocation
obj.each(
function(i,v) {
... v ...
// alternatively, v is identical to
... obj[i] ...
}
);
Run Code Online (Sandbox Code Playgroud)
当我确定我需要一个"范围循环"?它看起来更干净,应该具有与常规for循环类似的性能(因为它以相同的方式使用它).
更新:似乎做事Object.prototype是一个巨大的禁忌,因为它几乎打破了一切.
这是一个不那么具有侵入性的实现:
function each (obj,f) {
for (var i in obj) {
f(i,obj[i]);
}
}
Run Code Online (Sandbox Code Playgroud)
调用稍有变化
each(obj,
function(i,v) {
... v ...
}
);
Run Code Online (Sandbox Code Playgroud)
所以我想我已经回答了我自己的问题,如果jQuery这样做,不会真的出错.我忽略的任何问题都可以得到答案.
您的答案几乎涵盖了它,但我认为原始循环的更改值得注意,因为无论出于each()何种原因,当该函数不方便时,使用普通的 for 循环都是合理的。
更新:更改为使用与问题引用的示例类似的示例来比较不同的方法。该示例必须进行调整,因为该each()函数需要一个填充的数组来迭代。
假设以下设置:
var vals = ['a', 'b', 'c', 'd'],
max = vals.length,
closures = [],
i;
Run Code Online (Sandbox Code Playgroud)
使用问题中的示例,原始循环最终创建 2n 个函数(其中 n 是迭代次数),因为每次迭代期间都会创建两个函数:
for (i = 0; i < max; i++) {
closures[i] = (function(idx, val) { // 1st - factoryFn - captures the values as arguments
return function() { // 2nd - alertFn - uses the arguments instead
alert(idx + ' -> ' + val); // of the variables
};
})(i, vals[i]);
}
Run Code Online (Sandbox Code Playgroud)
通过在循环启动之前创建一次工厂函数,然后重用它,可以将其减少为仅创建 n + 1 个函数:
var factoryFn = function(idx, val) {
return function() {
alert(idx + ' -> ' + val);
};
};
for (i = 0; i < max; i++) {
closures[i] = factoryFn(i, vals[i]);
}
Run Code Online (Sandbox Code Playgroud)
这几乎相当于each()在这种情况下如何使用该函数,这也会导致总共创建 n + 1 个函数。工厂函数创建一次并立即作为参数传递给each().
each(vals, function(idx, val) {
closures[idx] = function() {
alert(idx + ' -> ' + val);
};
});
Run Code Online (Sandbox Code Playgroud)
FWIW,我认为使用的一个好处each()是代码有点短,并且在传递到函数时正确创建工厂函数each()清楚地说明了这是它的唯一用途。在我看来,循环版本的一个好处for是执行循环的代码就在那里,因此它的性质和行为是完全透明的,而函数each()可能在不同的文件中定义,由其他人编写等。
| 归档时间: |
|
| 查看次数: |
141 次 |
| 最近记录: |