2

Here's the code:

var InvertedPeninsula = function() {
  this.inhabitants = [
    {
      name: 'Sir Charles',
      race: 'Human'
    },
    {
      name: 'Ealei',
      race: 'Elf'
    }
  ];
  // Adds an extra humans method property to the inhabitants array to return all Humans
  this.inhabitants.humans = function() { /* returns all Human inhabitants */ };
};

// Create a new invertedPeninsula
var invertedPeninsula = new InvertedPeninsula();

// Log the name of each invertedPeninsula inhabitant
for (var i in invertedPeninsula.inhabitants) {
  console.log(invertedPeninsula.inhabitants[i].name);
}

To me, it looks like it's called 2x. Where does the 3x come from? There are only 2 cells in the array.

Mabeh Al-Zuq Yadeek
  • 46
  • 4
  • 16
  • 28

3 Answers3

7

This is exactly the pitfall one comes across when they use for...in to iterate an array. A for...in iterates through all the enumerable properties, and hence humans is being iterated too.

There are of course 2 objects in the array but for sure has three properties: 0, 1, humans and hence 3 times.

invertedPeninsula.inhabitants.forEach(function(habitat){
   console.log(habitat.name);
});

Array.forEach is your best bet as it iterates over numbered properties. A normal for loop would also do.

Amit Joki
  • 58,320
  • 7
  • 77
  • 95
1

Your array has the following values: 0, 1, 'humans' infact you added the element with the name 'humans' with the following code:

this.inhabitants.humans = function() { /* returns all Human inhabitants */ };

To check it try this code:

var InvertedPeninsula = function() {
  this.inhabitants = [
    {
      name: 'Sir Charles',
      race: 'Human'
    },
    {
      name: 'Ealei',
      race: 'Elf'
    }
  ];
  // Adds an extra humans method property to the inhabitants array to return all Humans
  this.inhabitants.humans = function() { /* returns all Human inhabitants */ };
};

// Create a new invertedPeninsula
var invertedPeninsula = new InvertedPeninsula();

// Log the name of each invertedPeninsula inhabitant
for (var i in invertedPeninsula.inhabitants) {
  console.log(i);   // CHANGED LINE
}
Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
1

for...in iterates all (inherited and own) enumerable properties.

When you create a property using an assignment, it is defined as enumerable. You can make it non-enumerable (and thus not iterated by for...in) using

Object.defineProperty(this.inhabitants, 'humans', {enumerable: false});

var InvertedPeninsula = function() {
  this.inhabitants = [
    {
      name: 'Sir Charles',
      race: 'Human'
    },
    {
      name: 'Ealei',
      race: 'Elf'
    }
  ];
  // Adds an extra humans method property to the inhabitants array to return all Humans
  this.inhabitants.humans = function() { /* returns all Human inhabitants */ };
  Object.defineProperty(this.inhabitants, 'humans', {enumerable: false});
};

// Create a new invertedPeninsula
var invertedPeninsula = new InvertedPeninsula();

// Log the name of each invertedPeninsula inhabitant
for (var i in invertedPeninsula.inhabitants) {
  console.log(invertedPeninsula.inhabitants[i].name);
}
Oriol
  • 274,082
  • 63
  • 437
  • 513