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 trialDillon Wyatt
5,990 PointsHelp: Pushing new objects into an array in JavaScript
Hello,
I am working through the JavaScript course now. Currently in the "JavaScript Loops, Arrays and Objects". While working on the objective of simply creating a list of objects in an array and then printing them, I decided to challenge myself more. To this end I tried to create a prompt set up that will do the following:
- Ask a series of 4 questions.
- Take the answers and create a new student object.
- Take that new student object and push it into a Students array.
- Log to the console the array.
My problem:
When I check the array in the console, even if I have inputted several students, only the last one is listed in the array. They will, however, be listed a number of times equal to the number of students I inputted. I am not sure why. Below is my JS code.
alert ("Hello");
var students = [];
var tempNewStudentStorage;
var newStudent = {
Name: "x",
Track: "y",
Achivement: 0,
Points: 0,
};
var finished;
var questions = [
"What is the student's name?",
"What Track(s) are they on?",
"What achivement(s) have they gotten?",
"What are their points?",
];
while (true) {
for (var i = 0; i < 4; i +=1) {
tempNewStudentStorage = prompt(questions[i]);
if (i === 0){
newStudent.Name = tempNewStudentStorage;
}
else if (i === 1){
newStudent.Track = tempNewStudentStorage;
}
else if (i === 2){
newStudent.Achievemnt = tempNewStudentStorage;
}
else if (i === 3){
newStudent.Points = tempNewStudentStorage;
};
};
students.push(newStudent);
finished = prompt("Are you done adding students? Y/N").toLowerCase();
while (finished.length > 1) {
finished = prompt("Are you done adding students? Y/N").toLowerCase()
};
if (finished === "y") {
alert("Thank you for adding a new student!")
break
}
else if (finished !== "y"){
continue;
};
};
console.log(students);
1 Answer
andren
28,558 PointsObjects behave a bit differently from most other datatypes in JavaScript. When you assign an object to a variable or add it to an array or anything like that. JavaScript does not make a copy of the object, it makes the new variable (or array item) contain the exact same object you assigned.
To illustrate this take a look at this code:
var example = {
message: "Hello"
};
var example2 = example;
example.message = "world";
console.log(example2);
We create an object example
then we create a new variable example2
and assign example
to it. Then we change the message
property of example
and then we print out example2
. Now what do you think will be printed out?
If Objects worked like Strings and Numbers then you would expect { message: 'Hello' }
to be printed out. Since that is what example
contained when it was assigned to example2
. But in reality the above code prints out { message: 'world' }
.
This is because these two variables don't hold independent copies of the object, they hold the exact same object. Which means that even though there are two variables at play there is actually only one object created in the above code. You just have two variables pointing at it.
With that knowledge if you take a look at your code the behavior you experience should make a bit more sense. You create one object at the start of your code, then you assign it the details of one student. Then you add a pointer to that object to the array. Then you change that same object with details of a new student. Since you in reality only have one object you end up changing the values of that one object each time the loop runs. And adding that object to the array multiple times just creates multiple pointers to it.
The solution to this issue is quite simple. Just create the object within the loop. Like this:
alert ("Hello");
var students = [];
var tempNewStudentStorage;
var finished;
var questions = [
"What is the student's name?",
"What Track(s) are they on?",
"What achivement(s) have they gotten?",
"What are their points?",
];
while (true) {
var newStudent = {
Name: "x",
Track: "y",
Achivement: 0,
Points: 0,
};
for (var i = 0; i < 4; i +=1) {
tempNewStudentStorage = prompt(questions[i]);
if (i === 0){
newStudent.Name = tempNewStudentStorage;
}
else if (i === 1){
newStudent.Track = tempNewStudentStorage;
}
else if (i === 2){
newStudent.Achievemnt = tempNewStudentStorage;
}
else if (i === 3){
newStudent.Points = tempNewStudentStorage;
};
};
students.push(newStudent);
finished = prompt("Are you done adding students? Y/N").toLowerCase();
while (finished.length > 1) {
finished = prompt("Are you done adding students? Y/N").toLowerCase()
};
if (finished === "y") {
alert("Thank you for adding a new student!")
break
}
else if (finished !== "y"){
continue;
};
};
console.log(students);
That way you actually create a new object each time the loop runs, instead of reusing the object created at the start of the script.
It's worth noting that Arrays and Functions also behave in the same way as I described above.
Dillon Wyatt
5,990 PointsDillon Wyatt
5,990 PointsThank you so very much for not only giving me the solution but an explanation for it! A true gentleman and scholar, you are!
To be completely honest, I am going to have to come back to this a couple times since I am trying to process exactly why this is the case. But at least I have a good springboard to launch from when trying to grasp it.
Thank you very kindly once again!
Steven Parker
231,268 PointsSteven Parker
231,268 PointsThe explanation above is good, but the code can be made more compact by assigning an empty object. It's not necessary to use the object literal since all the fields will be assigned separately in the loop: