7

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);
        }
    }
};
}
3
  • thanks everyone, very fast response time :) Commented May 5, 2012 at 22:31
  • That's Stack Overflow's specialty :D Commented May 5, 2012 at 22:33
  • Here is an exhaustive analysis of this code snippet: javascript.about.com/od/hintsandtips/a/foreach.htm Commented May 5, 2012 at 22:35

2 Answers 2

7

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"
Sign up to request clarification or add additional context in comments.

1 Comment

Maybe a more typical way of creating a sparse array: var a = []; a[3] == "d";.
3

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

This really has very little to do with the specific situation in question. No -1, but read the question a bit more carefully.
@Domenic - You're right I was too hasty. I have edited my answer to address the actual qu!
hmm one discrepancy I see is that Domenic has (x in arr) evaluate to true when the value at x is undefined, and you seem to have it evaluate to false. SHould it only be false when the value is absent completely?
Both 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.