Reputation: 9
I'm new to JavaScript and am learning about for...in loops and objects right now. I'm practicing with the following example:
let spaceship = {
crew: {
captain: {
name: 'Lily',
degree: 'Computer Engineering',
cheerTeam() { console.log('You got this!') }
},
'chief officer': {
name: 'Dan',
degree: 'Aerospace Engineering',
agree() { console.log('I agree, captain!') }
},
medic: {
name: 'Clementine',
degree: 'Physics',
announce() { console.log(`Jets on!`) } },
translator: {
name: 'Shauna',
degree: 'Conservation Science',
powerFuel() { console.log('The tank is full!') }
}
}
};
for (let crewMember in spaceship.crew){
console.log(`${crewMember}: ${crewMember.name}`);
}
The output of this code is that the console successfully logs crewMember, but not crewMember.name. crewMember.name is undefined, as in the image. On the other hand, when I change the log statement to this:
for (let crewMember in spaceship.crew){
console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
}
the name of the crew member is logged successfully. I don't understand why I am able to access the crew member without going through the spaceship.crew in the first half of the console.log statement, but in the second half I have to go through spaceship.crew.
Upvotes: -3
Views: 131
Reputation: 1
let spaceship = {
crew: {
captain: {
name: 'Lily',
degree: 'Computer Engineering',
cheerTeam() { console.log('You got this!') }
},
'chief officer': {
name: 'Dan',
degree: 'Aerospace Engineering',
agree() { console.log('I agree, captain!') }
},
medic: {
name: 'Clementine',
degree: 'Physics',
announce() { console.log(`Jets on!`) } },
translator: {
name: 'Shauna',
degree: 'Conservation Science',
powerFuel() { console.log('The tank is full!') }
}
}
};
for (let crewMember in spaceship.crew){
console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
}
Upvotes: -1
Reputation: 13304
As said in the comment.
The for...in
loop fetches the property name as a key
. So it's a placeholder for captain
or 'chief officer'
. You can access a property via dot notation and bracket notation. Use brackets when using variables:
so:
spaceship.crew[crewMember]
That should work. See example:
let spaceship = {
crew: {
captain: {
name: 'Lily',
degree: 'Computer Engineering',
cheerTeam() { console.log('You got this!') }
},
'chief officer': {
name: 'Dan',
degree: 'Aerospace Engineering',
agree() { console.log('I agree, captain!') }
},
medic: {
name: 'Clementine',
degree: 'Physics',
announce() { console.log(`Jets on!`) } },
translator: {
name: 'Shauna',
degree: 'Conservation Science',
powerFuel() { console.log('The tank is full!') }
}
}
};
for (let crewMember in spaceship.crew){
console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
}
And as Jared Smith said in his comment, use static methods instead:
So put of the objects own enumerable keys in an array using Object.keys
and iterate over them using forEach
and a Arrow function expression
.
let spaceship = {
crew: {
captain: {
name: 'Lily',
degree: 'Computer Engineering',
cheerTeam() { console.log('You got this!') }
},
'chief officer': {
name: 'Dan',
degree: 'Aerospace Engineering',
agree() { console.log('I agree, captain!') }
},
medic: {
name: 'Clementine',
degree: 'Physics',
announce() { console.log(`Jets on!`) } },
translator: {
name: 'Shauna',
degree: 'Conservation Science',
powerFuel() { console.log('The tank is full!') }
}
}
};
//Object.keys | return all the keys
Object.keys(spaceship.crew).forEach( crewMember => {
console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
});
//Object.entries | returns objects key and value in an array which you can iterate
Object.entries(spaceship.crew).forEach( ([crewMemberKey, crewDetails]) => {
console.log(`${crewMemberKey}: ${crewDetails.name}`);
});
Upvotes: 0
Reputation: 34217
Someone mentioned Object.entries(
which can also be used to add clarity from a properly formed object by coercing them into an array-like object so here is an example of that for the spaceship.crew
object we can use good names for crewMembers
an then crewMember
or just member
some such which can add clarity of purpose and intent also when we do this. Note this is less "brackety" since we have named properties of the objects. Note how crewMember
is an object then.
let spaceship = {
crew: {
captain: {
name: 'Lily',
degree: 'Computer Engineering',
cheerTeam() {
console.log('You got this!')
}
},
'chief officer': {
name: 'Dan',
degree: 'Aerospace Engineering',
agree() {
console.log('I agree, captain!')
}
},
medic: {
name: 'Clementine',
degree: 'Physics',
announce() {
console.log(`Jets on!`)
}
},
translator: {
name: 'Shauna',
degree: 'Conservation Science',
powerFuel() {
console.log('The tank is full!')
}
}
}
};
for (let crewMember in spaceship.crew) {
console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
}
//console.log(Object.entries(spaceship.crew));
//console.log([...Object.entries(spaceship.crew)]);
[...Object.entries(spaceship.crew)].forEach((crewMembers) => crewMembers.forEach(function(crewMember, index, mArray) {
console.log(crewMember, index);
console.log(`At ${index} We have ${crewMember.name}: ${crewMember.degree}`);
console.log(`And ${crewMember}`);
}));
Upvotes: 0