Javascript Custom Array.prototype interferes with for-in loops

I was trying to extend the type of a Javascript object with a function that fetches all the property names that are part of that object (basically what a PHP function does array_keys()

for associative arrays).

Object.prototype.keys = function() {
    var a = [];
    for (var property in this) {
        a.push(property);
    }
    return a;
};

var a = {a:1,b:2,c:3,d:4};
alert(a.toSource());

var b = a.keys();
alert(b.toSource());

      

When the variable was checked b

I expected to see ["a","b","c","d"]

, I see instead ["a","b","c","d","keys"]

.

The for-in seems to include prototyped functions keys()

.

Is it possible to avoid this behavior while it is still prototyping, or should I just avoid prototyping?

+2


source to share


3 answers


Ah - the joys of expanding built-in modules. for..in

checks the entire prototype chain of a repeating object.

What you need (and I believe it is de facto now) is a check with hasOwnProperty

in your loop:



for (var property in this) {
    if (this.hasOwnProperty(property)) {
        a.push(property);
    }
}

      

hasOwnProperty

ensures that you only get properties that are directly defined on your object (i.e. not up the prototype chain).

+12


source


In most situations, you should avoid extending native Object.prototype

. When you expand it, objects ALL get these new properties.

Looping through the properties of an object is a really common task, and as you've noticed, you've encountered unexpected behavior.

I haven't seen many people always use a function hasOwnProperty

in their code, I would say that in "controlled environments", perhaps as a solo developer working on a project, you can manage these issues, but when things get bigger and you have more developers involved, this can cause many problems.



How do I make a static function for Object?

Object.keys = function(obj) {
  var a = [];
  for (var property in obj) {
    if (obj.hasOwnProperty(property)) {
      a.push(property);
    }
  }
  return a;
};

var a = {a:1,b:2,c:3,d:4};
alert(a.toSource());

var b = Object.keys(a);
alert(b.toSource());

      

+4


source


This also works:

var items = [
    {
        id: 1, name: 'Item 1'
    },
    {
        id: 2, name: 'Item 2'
    },
    {
        id: 3, name: 'Item 3'
    }
];
items.forEach(function(item, index) {
    console.log(item);
});

      

0


source







All Articles