0

I'm currently trying to get my head around using prototype in JavaScript.

To experiment with this, I've written a function that effectively works as allowing you to put a where clause onto arrays:

Array.prototype.where=(function(){
  var tmpArr=[],
      success;

  for (var x in this){
    var success=true;
    for (var i in arguments){
      if (this[x][arguments[i][0]]!=arguments[i][1]){
        success=false;
        break;
      }
    }

    if (success==true){
      tmpArr.push(this[x]);
    }
  }
  return tmpArr;
});

An example use would be:

arrayName.where([0, 'Fred'], [1, 'Bloggs']);

For the sake of a test, this works pretty well. The only problem is if you were then to run

for (var x in someArrayHere){
  console.log(someArrayHere[x]);
}

You get the output the array, but with a record representing the function you've prototyped.

As far as I can work out, this is sorted by setting the function as non-enumerable, but I can't find any articles explaining how to stop it.

How would I go about it? Or would I have to do the below each time?

for (var x in someArray){
  if (typeof tSch[x]!="object"){
  }
}
Doug
  • 3,312
  • 1
  • 24
  • 31

3 Answers3

2

The for...in construct enumerates all properties of an object (and those inherited down the prototype chain). When you use it with an array, it will iterate over all properties of Array.prototype, as well as the elements of the array.

Use a normal for loop to prevent this:

for(var x = 0; x < this.length; x++) {
    //Do stuff
}
James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • Well, that's a shame =[ Thanks! – Doug Jan 16 '12 at 10:25
  • No problem. Note that you can work around this with `Object.hasOwnProperty` as mentioned in a couple of other answers. The reason I didn't mention that is that it's pretty bad practice. You probably just shouldn't use `for...in` with native objects! – James Allardice Jan 16 '12 at 10:29
  • Another possible solution would be to use the native `Array.prototype.forEach` method where available, and use a shim if not: https://github.com/kriskowal/es5-shim/ – James Allardice Jan 16 '12 at 10:32
1

In general, using a for ... in loop to iterate through an array is bad practice.

However, a simple fix would be to use Object.hasOwnProperty:

for (var x in someArray) {
  if (someArray.hasOwnProperty(x)) {
    //...
  }
}

This is a more robust approach than your loop.

Tikhon Jelvis
  • 67,485
  • 18
  • 177
  • 214
0

In general, you should not mess with the prototypes of native Objects. This leads to problems - especially in combination with extern code/libraries.

Instead, you should make it a function that operates on an array parameter (for instance function arrayWhere(arr)).

If you want to stick to extending native prototypes, you should iterate over arrays with the forEach method (newer browsers, maybe add a fallback as described at the MDN), or the hasOwnProperty method of objects, as described in this example.

copy
  • 3,301
  • 2
  • 29
  • 36