I found a code snippet for a forEach function on a tutorial website, and everything makes good sense to me except for the line that checks if i is in the array:
if (i in this) {
Why bother if we already have a for loop that has a stop condition?
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(fun /*, thisp*/) {
var len = this.length >>> 0;
if (typeof fun != "function") {
throw new TypeError();
}
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) {
fun.call(thisp, this[i], i, this);
}
}
};
}
-
thanks everyone, very fast response time :)worker1138– worker11382012年05月05日 22:31:43 +00:00Commented May 5, 2012 at 22:31
-
That's Stack Overflow's specialty :DDomenic– Domenic2012年05月05日 22:33:52 +00:00Commented May 5, 2012 at 22:33
-
Here is an exhaustive analysis of this code snippet: javascript.about.com/od/hintsandtips/a/foreach.htmJulian D.– Julian D.2012年05月05日 22:35:54 +00:00Commented May 5, 2012 at 22:35
2 Answers 2
Two reasons:
1. Mutation by the callback
Calling fun might change the array, since fun is entirely user-defined. So you need to check again.
Example:
array.forEach(function (el, i) { delete array[i + 1]; });
2. Sparse arrays
The other issue is that there can be sparse arrays: e.g.
3 in ["a", "b", "c", , "e", "f"] === false
// even though
3 in ["a", "b", "c", undefined, "e", "f"] === true
In those cases you don't want to call fun for that index/element, since there is nothing at that index.
["a", "b", "c", , "e", "f"].forEach(function (el, i) {
console.log(el + " at " + i);
});
// => "a at 0" "b at 1" "c at 2" "e at 4" "f at 5"
1 Comment
var a = []; a[3] == "d";.Because an array can have holes, and therefore you can iterate over the length and not all values will exist.
x = new Array()
[]
x[0] = "zero"
"zero"
x[5] = "five"
"five"
x
["zero", undefined ×ばつ 4, "five"]
3 in x
false
x.length
6
for (var i = 0; i < x.length; i++) { console.log(i, i in x, x[i])}
0 true "zero"
1 false undefined
2 false undefined
3 false undefined
4 false undefined
5 true "five"
4 Comments
null and undefined are actually values in JavaScript (you can assign them, as he did in his example). The output in my answer come from the Chrome JavaScript tools. Look at this: ["a", undefined , "f"] -> ["a", undefined, "f"] ["a", , "f"] -> ["a", undefined × 1, "f"]. Notice the difference in how they are printed. I think it's just down to how the console deals with printing sparse holes.