0

Due to the problem I posted here Mootools when using For(...in Array) problem about some javascript framework will prototype the Array object, and some other's codes(a forum engine) did use For...in Loop to loop Arrays, when I plug the javascript framework into these existing codes, things will go wrong.

//BEFORE
for(key in [1,2,3,4]) console.log(key)    //0,1,2,3 keys of the array

//After JS Framework
for(key in [1,2,3,4]) console.log(key)    //0,1,2,3,$family,$constructor,pop,push,reverse,shift,sort,splice

Given that I cannot touch the original codes which contains these For..In Array loops, and I also want to use the javascript framework (mootools)

Can I work around this by e.g. prototype the javascript Iterator??

somehow to overload the For...In loop, to make all my javascript For...in loop to scan for array type and only return the value but not the function? I donno how to do this but i wonder if this can be done?

2
  • The original code is broken... that is really a shame. Commented Aug 12, 2011 at 5:59
  • 1
    Sigh. Extending Array is ok. perfectionkills.com/…. However, looping an array through the for ... in construct, meant to be used on OBJECTS, is wrong. It works, because arrays are really objects with array-like properties but you ought to use a normal for loop, Array.each or Object.each as appropriate. if you HAVE to use for .. in ALWAYS check hasOwnProperty. Commented Aug 12, 2011 at 8:25

4 Answers 4

2

The original code is broken... that is really a shame.

With Mozilla JavaScript -- don't confuse the Mozilla JavaScript extensions with ECMAScript -- it is possible to define a custom Iterator for the object. See What's new in JavaScript 1.7. However, this is likely not practical in this scenario.

My suggestions are thus:

  1. Fix the code
    • It should use hasOwnProperty for key iteration, or;
    • i < arr.length for array index iteration.
  2. Keep mootools from messing with prototypes of built-in objects.
    • Refer to the mootools documentation (I don't use mootools).
  3. Use a framework that doesn't mess with the prototypes of built-in objects.
    • jQuery doesn't mess with prototypes.

Happy coding.

Sign up to request clarification or add additional context in comments.

2 Comments

on suggestion 3, why should that be a problem? if you are worth your salt, you won't have problems getting your code to function fine with mootools. mootools only extends/shims native objects in a way that conforms with ES5 specs, deviations and additions to that are really edge cases. not knowing how to loop arrays does not constitute as a mootools shortcoming, imo. it does not have to be mootools, anything could affect the protos. for suggestion 2, mootools 2.0 will have a `uninstall' function that removes all host and native object extensions, though it is not yet available.
@Dimitar Christoff I wrote the bullets in order of my suggestion and using another library came last. One of the original constraints was that the original code is not alterable (although my first suggestion is to fix it anyway ;-). I applaud mootools 2.0 for having an "non intrusive mode" -- while it would be nice to assume that the world runs universally on ECMAScript ed.5, it does not yet and will sadly not be guaranteed as such for awhile :-/ user608886 posted an answer involving deleting the prototype'd methods (which may be very detrimental in other ways, I know not).
1

Store the array in a variable and then iterate over it like this:

var items = [1,2,3,4];

for(var i = 0; i < items.length; i++) {
    console.log(i);
}

Comments

1

Do not use for (key in array) logic on arrays. It is meant for iterating object properties, not for iterating arrays. As you can see, when you use it on arrays, you get all the properties of the array, including non-native properties/methods that have been added.

You should iterate an array with this type of for loop:

for (var i = 0; i < array.length; i++) {
     item = array[i];
}

Yes, it seems a bummer that we can't use the shorter syntax on arrays, but that's the way the language is.

It is possible to try to work around this issue with:

for (key in array) {
    if (array.hasOwnProperty(key)) {
        // operate on array[key] here
    }
}

But, I wouldn't recommend it. It's just safer all around to use the iterator meant for arrays.

Comments

0

Prototype functions can be easily removed with "delete", but frameworks tend to rely on them so it's not a good idea.

delete Array.prototype.$family;
delete Array.prototype.$constructor;
delete Array.prototype.pop;
delete Array.prototype.push;
...

The bad of it is that there's no easy option at hand. You can either:

  1. Create a parser for the forum's script files, and add a numeric key validation inside the for, using regular expressions (this is highly redneck but will do the trick)
  2. Create another class Array2 and replace the entire framework to use this one instead of regular arrays (this is also redneck as you might need other plug-ins later)
  3. Do the right thing and think about migrating the entire forum to something more flexible

Comments

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.