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
  • 172
  • 3
  • 13
  • 24

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
  • 56,285
  • 7
  • 72
  • 91
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
  • 25,114
  • 4
  • 37
  • 52
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
  • 249,902
  • 55
  • 405
  • 483