Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Mark DiPaola
9,254 PointsProblem with Object Property Access
The objective of the program is to randomly pull objects from one main array, for placement in two separate player arrays.
From the two separate player arrays, I should be able to display the object attributes in the HTML.
The issue is that the object attributes (such as name, health, etc) are not accessible when working with them within a function. The error I get is: Uncaught TypeError: Cannot read property 'name' of undefined
Here is the JavaScript Code: (It's long, I know. The summon1 and summon2 functions, as well as the display functions are where the problem arises. Using dot notation to display a monster name, for example, seems like a pretty routine thing, but in this case has not been so.
Any advice is greatly appreciated!)
JavaScript
//the monsters...
var cerberus= {
name: "Cerberus",
health: 550,
power: 65,
firstStrike: 474,
evade: 1150,
attacks: [
gullotine= {
attackName: "Gullotine",
maxImpact: 1250,
maxAccuracy: 600
},
howlOfHell= {
attackName: "Howl of Hell",
maxImpact: 150,
maxAccuracy: 800
}
]
}
var kraken= {
name: "Kraken",
health: 860,
power: 65,
firstStrike: 1000,
evade: 200,
attacks: [
thrash= {
attackName: "Thrash",
maxImpact: 400,
maxAccuracy: 600
},
strangle= {
attackName: "Strangle",
maxImpact: 900,
maxAccuracy: 300
}
]
}
var minotaur= {
name: "Minotaur",
health: 625,
power: 85,
firstStrike: 152,
evade: 400,
attacks: [
axSwipe= {
attackName: "Ax Swipe",
maxImpact: 500,
maxAccuracy: 600
},
ragingBull= {
attackName: "Raging Bull",
maxImpact: 600,
maxAccuracy: 400
}
]
}
var hydra= {
name: "Hydra",
health: 1300,
picture: hydraImg,
firstStrike: 164,
evade: 50,
attacks: [
spewVenom= {
attackName: "Spew Venom",
maxImpact: 750,
maxAccuracy: 550
},
spewFlames= {
attackName: "Spew Flames",
maxImpact: 650,
maxAccuracy: 600
}
]
}
var ctulu= {
name: "Ctulu",
health: 1000,
power: 500,
firstStrike: 900,
evade: 800,
attacks: [
oblivion= {
attackName: "Oblivion",
maxImpact: 500,
maxAccuracy: 3000
},
darknessFalls= {
attackName: "Darkness Falls",
maxImpact: 1100,
maxAccuracy: 3000
}
]
}
var balrog= {
name: "Balrog",
health: 850,
power: 600,
firstStrike: 740,
evade: 100,
attacks: [
whiplash= {
attackName: "Whiplash",
maxImpact: 250,
maxAccuracy: 500
},
greatBallOfFire= {
attackName: "Great Ball of Fire",
maxImpact: 550,
maxAccuracy: 300
}
]
}
var cyberDemon= {
name: "Cyber Demon",
health: 950,
power: 890,
firstStrike: 400,
evade: 400,
attacks: [
hellFireCannon= {
attackName: "Hell Fire Cannon",
maxImpact: 500,
maxAccuracy: 700
},
curbStomp= {
attackName: "Curb Stomp",
maxImpact: 1100,
maxAccuracy: 300
}
]
}
var apocalypse= {
name: "Apocalypse",
health: 800,
power: 65,
firstStrike: 300,
evade: 400,
attacks: [
dustToDust= {
attackName: "Dust to Dust",
maxImpact: 900,
maxAccuracy: 2000
},
ashToAsh= {
attackName: "Ash to Ash",
maxImpact: 400,
maxAccuracy: 1500
}
]
}
var zeus= {
name: "Zeus",
health: 1200,
power: 65,
firstStrike: 500,
evade: 1000,
attacks: [
boltOfLightning= {
attackName: "Bolt of Lightning",
maxImpact: 950,
maxAccuracy: 900
},
fistOfGod= {
attackName: "Fist of God",
maxImpact: 1000,
maxAccuracy: 600
}
]
}
var cronos= {
name: "Cronos",
health: 1500,
power: 65,
firstStrike: 100,
evade: 10,
attacks: [
titanBreath= {
attackName: "Titan Breath",
maxImpact: 400,
maxAccuracy: 450
},
heavyHand= {
attackName: "Heavy Hand",
maxImpact: 600,
maxAccuracy: 200
}
]
}
var kratos= {
name: "Kratos",
health: 700,
power: 65,
firstStrike: 600,
evade: 1200,
attacks: [
bladesOfAthena= {
attackName: "Blades of Athena",
maxImpact: 700,
maxAccuracy: 350
},
rampage= {
attackName: "Rampage of the Furies",
maxImpact: 400,
maxAccuracy: 500
}
]
}
var aries= {
name: "Aries",
health: 880,
power: 65,
firstStrike: 700,
evade: 700,
attacks: [
hammer= {
attackName: "Sledge Hammer Strike",
maxImpact: 650,
maxAccuracy: 100
},
rocks= {
attackName: "Rocks Rain",
maxImpact: 500,
maxAccuracy: 200
}
]
}
//the main array
var monsters= [cerberus, minotaur, hydra, ctulu, balrog, cyberDemon, apocalypse, kraken, zeus, aries, cronos, kratos];
//capturing from the main array...
var monstersIndex= 0; //by default...
var thisMonster= monsters[monstersIndex]; //the object picked
//the roster for player 1, to be filled at start...
var player1List= [];
//the roster for player 2, to be filled at start...
var player2List= [];
var monsterName= thisMonster.name;
//the functions that FILL...
//player 1 list...
var summon1= function() {
while(player1List.length < 3) {
monstersIndex= Math.floor(Math.random * monsters.length);
thisMonster= monsters[monstersIndex];
player1List.push(thisMonster);
monsterName= thisMonster.name;
alert(monsterName + ' has been added to player 1 roster.');
monsters.splice(monstersIndex, 1);
alert('Monster array length is ' + monsters.length);
}
}
//player 2 list...
var summon2= function() {
while(player2List.length < 3) {
monstersIndex= Math.floor(Math.random * monsters.length);
thisMonster= monsters[monstersIndex];
player2List.push(thisMonster);
monsterName= thisMonster.name;
alert(monsterName + ' has been added to player 2 roster.');
monsters.splice(monstersIndex, 1);
alert('Monster array length is ' + monsters.length);
}
}
summon1();
summon2();
//once that is done, we turn to player1List AND player2List...
//capturing from player 1 list...
var player1Index= 0;
var player1Monster= player1List[player1Index];
//from player 2 list...
var player2Index= 0;
var player2Monster= player2List[player2Index];
//player 1 set up, at click of summon Button...
var player1Display= function() {
player1Name.innerHTML= '<p>' + player1Monster.name +
'</p>';
player1Health.innerHTML= '<p>Health: ' + player1Monster.health + '</p>';
player1Attack0.innerHTML= '<p>' + player1Monster.attacks[0].attackName + '</p>';
player1Impact0.innerHTML= '<p>' + player1Monster.attacks[0].maxImpact + '</p>';
player1Dodge0.innerHTML= '<p>' + player1Monster.attacks[0].maxAccuracy + '</p>';
player1Attack1.innerHTML= '<p>' + player1Monster.attacks[1].attackName + '</p>';
player1Impact1.innerHTML= '<p>' + player1Monster.attacks[1].maxImpact + '</p>';
player1Dodge1.innerHTML= '<p>' + player1Monster.attacks[1].maxAccuracy + '</p>';
}
//player 2 set up, at click of summon Button...
var player2Display= function() {
player2Name.innerHTML= '<p>' + player2Monster.name + '</p>';
player2Health.innerHTML= '<p>Health: ' + player2Monster.health + '</p>';
player2Attack0.innerHTML= '<p>' + player2Monster.attacks[0].attackName + '</p>';
player2Impact0.innerHTML= '<p>' + player2Monster.attacks[0].maxImpact + '</p>';
player2Dodge0.innerHTML= '<p>' + player2Monster.attacks[0].maxAccuracy + '</p>';
player2Attack1.innerHTML= '<p>' + player2Monster.attacks[1].attackName + '</p>';
player2Impact1.innerHTML= '<p>' + player2Monster.attacks[1].maxImpact + '</p>';
player2Dodge1.innerHTML= '<p>' + player2Monster.attacks[1].maxAccuracy + '</p>';
}
//summon button(s) functionality...
summonBtn1.onclick= function() {
player1Img.removeChild(summonBtn1); //remove summon button when clicked...
player1Display(); //display monster name and attack attributes
}
summonBtn2.onclick= function() {
player2Img.removeChild(summonBtn2);
player2Display();
}
3 Answers
Stephan Olsen
6,650 PointsIt's a very long code, it would help a lot if you could narrow it down a bit or include the whole code in a proper format. You can see the Markdown Cheatsheet for information about formatting your post.
Mark DiPaola
9,254 PointsThanks-will do. I'm a bit new to the forum, so I'll try to get it reformatted as soon as I figure out the best way.
Stephan Olsen
6,650 PointsThe reason why you can't access the name property, is because you you're not retrieving an object when setting the value of the monster. You're creating an array of monsters, and then setting thisMonster to a random monster in the array. The array you're getting the values from are not objects, which means they have no properties.
var monsters= [cerberus, minotaur, hydra, ctulu, balrog, cyberDemon, apocalypse, kraken, zeus, aries, cronos, kratos];
var monstersIndex= 0;
var thisMonster= monsters[monstersIndex];
// thisMonster = "Cerberus"
So you're basically thisMonster to be a string from the array, instead of an object that contains the properties of the monster. What you should do, is keep all your monsters in an array, so you have an array of objects. Something like this
var monsters = [
{
name: "Cerberus",
health: 550,
power: 65
},
{
name: "Kraken",
health: 860,
power: 65
}
];
// This will store the object in the variable
var thisMonster = monsters[0];
// Alert the monster name
alert(thisMonster.name); // Will alert "Cerberus"
Mark DiPaola
9,254 PointsThanks, Stephan. I'm reworking the array based on your response and so far, so good. I appreciate the help.
Stephan Olsen
6,650 PointsNo problem :) Good luck!
Mark DiPaola
9,254 PointsMark DiPaola
9,254 PointsOkay-pared the code down to what (I think) are its must-know components. Let me know if it still looks a little too long. Thanks again.