1

I've tried to add some new functions to the Array prototype, that I use frequently. My question is how when I add something to the prototype of an Object, and trace out properties in a for-in loop of any new array (object) that I created, those new functions that were added only to the prototype are listed as well? Shouldn't they just be in proto?

Just for example: So I add an function of "first" to the prototype.

Array.prototype.first = function() { return this[0]; }

So when now I use an for-in loop to iterate over the array, I get the named function, as well as any other items that are in the array.

var array = [1,2,3];   

//traces out: 1,3,4,first
for(var i in array) {
   console.log(i);
}

Is this something that is solely resulting from the trace and/or use of for-in for iterating over an object?

lislis
  • 294
  • 5
  • 23

3 Answers3

2

Evan is correct. However, when using for..in statements in javascript, it is always best to test that the current attribute is a property of the object and not something inherited from the prototype chain:

for(var attr in obj){
   if(obj.hasOwnProperty(attr)){
       // first will not appear here
   }
}
Rob M.
  • 35,491
  • 6
  • 51
  • 50
  • Ah, I see. So using an hasOwnProperty() to check only for properties vs. inherited from the prototype chain. Thanks for the response Rob. – lislis Nov 18 '13 at 23:24
  • My pleasure, this is something a lot of people find confusing. Maurice is also correct in saying that extending the prototype of native js objects is considered bad practice. http://en.wikipedia.org/wiki/Prototype_JavaScript_Framework#Problems – Rob M. Nov 18 '13 at 23:27
  • And here I was about to add a bunch of prototypes to Array, String and Date. If you make them non-enumerable though, as in Maurice's answer, what is the real danger in adding prototypes to native Objects? I guess that if you extended the prototype with the same function names as others as in an included library, then would the original be overwritten or something? That's the only thing that comes to mind. – Chris Cirefice Nov 18 '13 at 23:31
  • Name collisions are one of the main problems, it also can add a significant amount of overhead depending on what you extend. An in depth article on this subject can be found here: http://perfectionkills.com/whats-wrong-with-extending-the-dom/ – Rob M. Nov 18 '13 at 23:39
1

You shouldn't use a for-in loop to loop over an array.

for (var i = 0, len = arr.length; i < len; ++i) {
}

for in is used for iterating the keys of an object.

Evan Trimboli
  • 29,900
  • 6
  • 45
  • 66
1

If you really need to do this, use

Object.defineProperty(Array.prototype, 'first', {
    value: function() { return this[0]; },
    enumerable: false
});

But some consider this a bad practice. Think twice before doing it.

Maurice Lam
  • 1,577
  • 9
  • 14
  • Thanks Maurice for pointing that out, and the alternative way to do it if need-be. – lislis Nov 18 '13 at 23:31
  • As for the reasons why not to do it: 1. Usually the for in breaks (you fixed but not all browsers support it and can't be polyfilled). 2. Conflict with future browser implementation or other code. – HMR Nov 19 '13 at 03:47
  • @leetou the alternative way would be to just create a function named first and invoke it like this: `first.call(someArray);` Maybe the following link will be helpful to you: http://stackoverflow.com/a/16063711/1641941 – HMR Nov 19 '13 at 03:48