7

We all know that for-in-loops on arrays are absolutely evil. Still, they are often used and the caused errors are complicated to trace down, especially when happening browser-dependent for example because of indexOf-shims or such.

So, I have coded this simple snippet which adds an enumerable getter for a "error" property on Array.prototype (not for use in production code):

Object.defineProperty(Array.prototype, "error", {
    enumerable: true,
    get: function() {
        if (this === Array.prototype) // that looks OK
            return undefined;
        if (window.confirm("Somebody who coded the site you're viewing runs through an Array with a for-in-loop.\nShame on him!\n\nDo you want to raise an Error to trace the origin?"))
            throw new SyntaxError("Array traverse with for-in-loop, touching Array.prototype's 'error' property :-)");
    }
});

You can add it as a greasemonkey script for all domains, and you will see alerts on nearly every site :-) Most of them are caused by calls to jQuery.extend with questionable arguments, btw.

My question is now: Are there any situations that legitimate such "wrong" loops, or anything else causing false-positive alerts?

I am wondering how this would affect the usefulness of my code.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I edited your question to make it less subjective. I hope you don't mind. – hugomg Jul 16 '12 at 15:35
  • Thanks, I like that version - I had no clue what to use as title :-) – Bergi Jul 16 '12 at 15:37
  • I don't get it, how do you extend this to `Array.prototype`? You'd need to use `__lookupGetter__` or something. It will now simply cause an error because the extend function will get it and the error is thrown and stopping the copying. http://jsfiddle.net/MvgJC/ – Esailija Jul 17 '12 at 20:47
  • Not if you'd use `Object.getOwnPropertyNames(o).each(function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(o,n));})` as the extend function instead of jQuery's one (that's why I had written `Object.extend`)... – Bergi Jul 17 '12 at 20:59

1 Answers1

-1

Yes. Legitimacy can often be subjective, but...

As an example, perhaps I have a sparse array, where I have only set values at the indexes with data:

var a = [];
a[123123] = "foo";
a[1233123] = "bar";

If I wanted to iterate over the elements that I defined in this array, then I would use the for...in construct. Even if I coded it defensively, your script would still trigger (a false positive)...

for (var prop in a) {
  if (a.hasOwnProperty(prop)) {
    // this is a legitimate array element
  }
}

See also Why is using "for...in" with array iteration a bad idea? for more information and opinions.

Community
  • 1
  • 1
Steve Campbell
  • 3,385
  • 1
  • 31
  • 43
  • 3
    No, the defensively coded loop (which is fine) will never access `a[prop]` where `prop` is `"error"`, so it's not raising the exception. – Bergi Jun 03 '13 at 21:38