Gustavo
Gustavo

Reputation: 1683

Javascript: prototype x defineProperty x what else

I have some small but useful extra methods for JS core objects like Array:

Array.prototype.indexOfObject(property, value)

This method returns the index of an Object in a Array (of Objects) where property==value, simple and productive for me.

However, when I do enumerate any Array, the method will show up, so every time I got to do like this:

for(var i in MyArray){
  if(typeof(MyArray[i])=="typeneeded"){
    // do something
  }
}

As I know, defineProperty make a non enumerable method so it will solve my problem when all browsers do accept it. By the way, is it already safe use defineProperty? IE9 works well? Other browsers? Is there a third way of doing this?

Upvotes: 2

Views: 201

Answers (3)

Xitalogy
Xitalogy

Reputation: 1612

Just use a traditional for loop, or forEach:

var i,
    ary = ['val0', 'val1', 'val2'];

Array.prototype.getElem = function (i) {
    return this[i];
};

console.log('First way - using standard for loop:');
for (i = 0; i < ary.length; i++) {
    console.log('Element ' + i + ' has value ' + ary[i]);
}

console.log('second way - use "first order function" - "functional programming" style');
ary.forEach(function (e, i) {
    console.log('Element ' + i + ' has value ' + ary[i]);
});

console.log('getElem says: element 2 has value ' + ary.getElem(2));

FIDDLE

Upvotes: 1

HMR
HMR

Reputation: 39280

You can use hasOwnproperty safely for all browsers but your question was about Object.defineProperty. If you're not worried about old browsers (IE8) then you can use this:

//you should reload when you want to change value
//or you'll get a can't redefine error
Object.defineProperty(Array.prototype,"someFn",{
  enumerable: false,
  configurable: false,
  writable: false,
  value: function(){console.log("my fn");}  
});

var a = [1,2,3,4];
for(thing in a){
  console.log(thing);//=0,1,2,3
}
a.someFn();//=my fn

Upvotes: 1

RobG
RobG

Reputation: 147413

There are a few ECMAScript compatibility matrices around: kangax's is good for ES5 only, Thomas Lahn's will tell you which features are supported in what versions of various ECMAScript implementations.

A "third way" is to use a hasOwnProperty test, which works in all browsers and is a good idea in any environment that you don't control completely:

for (var p in obj) {

  if (obj.hasOwnProperty(p)) {

    // p is an own property of obj
    // do stuff with obj[p]
  }
}

You can also use Object.keys, which only returns own properties too, but support might be less than for defineProperty.

You should also note that for..in does not necessarily return properties in any particular order and can be shown to return them in different orders in different browsers. So only use it with an Array where the order of accessing members isn't important.

PS. You can also use propertyIsEnumerable too, as it only returns true for properties on the object itself:

if (obj.propertyIsEnumerable(p)) {

This was used to accommodate a bug in early Safari, but that version shouldn't be in use any more.

Incidentally, in:

> typeof(MyArray[i])

there is no need for the brackets, typeof is an operator. Also, checking the Type of a property doesn't tell you if it's an own property of the object or not, or even if it exists (though in this case it does because it's come from for..in).

Upvotes: 3

Related Questions