0

I'm working in a large legacy codebase and just realized that someone did this:

Array.prototype.insertAt = function (i,el){ return this.splice(i,0,el); }
Array.prototype.deleteAt = function (i){return this.splice(i, 1); }

and that this is the reason i can't to this:

var derp = new Array();
derp.push('duh');
derp.push('what?');

for (var i in derp) {
    console.log(derp[i]);
}

Well, it's not that i can't do it, but if i do, i get unexpected results. That being instead of getting two lines of output (for 'duh' and 'what?') i get four. the last two being the two functions listed above.

I don't want to remove the original prototype functions (because god knows what depends on them), but i am wondering if there is a way to prevent the for loop from looping over the functions that were added.

Dallas Caley
  • 5,367
  • 6
  • 40
  • 69
  • 3
    `for..in` is purposed to iterate objects. Use a regular `for` loop instead. – Teemu Jan 29 '16 at 16:45
  • 3
    Agree with using for loops - http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such-a-bad-idea – IrkenInvader Jan 29 '16 at 16:46
  • 1
    I like both of these comments better than any of the official answers because i learned that i shouldn't be using for .. in in the first place. thanks – Dallas Caley Jan 29 '16 at 16:54

3 Answers3

3

Use .forEach to iterate over an array or a regular for loop. for in is meant for object iteration and will include all properties on the prototype (which is why Object.keys(obj).forEach is preferred for object iteration as it does a hasOwnProperty check internally)

  • You're not considering legacy browser support for this method. This method is not available prior to IE9. – idream1nC0de Jan 29 '16 at 16:47
  • @JacobHeater: Just use a polyfill. – gen_Eric Jan 29 '16 at 16:48
  • @RocketHazmat You're overcomplicating the solution. – idream1nC0de Jan 29 '16 at 16:49
  • a regular for loop isn't available prior to IE9? I believe I gave two options in my answer, and expounded upon enumerable prototype properties. OP has every ability to look further into each one of the methods listed. –  Jan 29 '16 at 16:52
  • @gabdallah Apologies! I should've read the answer more carefully. Correction: The Array.prototype.forEach method is not available prior to IE9. A for loop, of course, is! – idream1nC0de Jan 29 '16 at 16:54
3

Method 1: Use a regular for (best supported)

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

Method 2: Use hasOwnProperty

for(var i in arr){
 if(arr.hasOwnProperty(i)){
     console.log(i)
  }
}

Method 3: Use Object.defineProperty:

Object.defineProperty(Array.prototype, 'insertAt', {
    writeable: true,
    enumerable: false,
    value: Array.prototype.insertAt
})
Object.defineProperty(Array.prototype, 'deleteAt', {
    writeable: true,
    enumerable: false,
    value: Array.prototype.deleteAt
})

for(var i in derp){
    console.log(derp[i])
}

Which one you use depends on your browser support, last one prevents changing all for code written though

juvian
  • 15,875
  • 2
  • 37
  • 38
0
for (var i in derp) {
    if(derp.hasOwnProperty(i)) 
        console.log(derp[i]);
}

But then, normal for loop is far better for Array than using for-in (which is actually for Object)

for (var i = 0; i < derp.length; i++) { 
    console.log(derp[i]);
}
Oxi
  • 2,918
  • 17
  • 28