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

JavaScript JavaScript Loops, Arrays and Objects Tracking Data Using Objects The Build an Object Challenge, Part 2 Solution

Dillon Wyatt
Dillon Wyatt
5,990 Points

Help: 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:

  1. Ask a series of 4 questions.
  2. Take the answers and create a new student object.
  3. Take that new student object and push it into a Students array.
  4. 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
andren
28,558 Points

Objects 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
Dillon Wyatt
5,990 Points

Thank 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
Steven Parker
229,732 Points

The 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:

while (true) {
    var newStudent = {};  // start with a fresh empty object;