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

Here's mine. Is it supposed to be so different?

I was very discouraged when I saw that the solution in this video was nothing like mine. But I was trying to use the tools that had been learned earlier in the course up until now, and keep it DRY. I feel like the instructor did the opposite of that. Am I missing something? Do I need to do it all over again? I'm lost.

My code works. But I want to know that I'm on the right track. No, I didn't link a separate JavaScript file; I don't recall us ever doing that in this course...

let students = [
  {
    Student: 'Tom', 
    Track: 'iOS',
    Achievements: 4,
    Points: 9000
  },
  {
    Student:'Billy', 
    Track: 'JavaScript',
    Achievements: 3,
    Points: 2015
  },
  {
    Student: 'Sandra', 
    Track: 'Web Design',
    Achievements: 6,
    Points: 7400
  },
  {
    Student: 'Jonny', 
    Track: 'Python',
    Achievements: 4,
    Points: 1756
  },
  {
    Student: 'Nathan', 
    Track: 'Linux',
    Achievements: 2,
    Points: 1089
  }
];

function print (message) {
  let outputDiv = document.getElementById('output');
  outputDiv.innerHTML = message;
}

function printList ( classList ) {
  let listHTML = '<p>';
  for (i = 0; i < students.length; i += 1) {    
    for (let prop in students[i]) {
      if (prop === 'Student') {
        listHTML += '<h2>' + prop + ': ' + students[i].Student + '</h2></p>';
      } else {
        listHTML += '<p>' + prop + ': ' + students[i][prop] + '</p>'
      }
    }    
  }
  return(listHTML);  
}

html = printList(students);
print(html);

3 Answers

Michael Hulet
Michael Hulet
47,912 Points

I'll be honest, I think I like your code better than the teacher's. The teacher hardcodes the keys to display from his objects, but yours loops through the keys instead. This makes your code more resilient to changes in the data, which is definitely a good thing. As for the separating out into separate files, it's greatly a matter of preference. It's generally good to keep your data separate from your code, but if I was thinking about that, I'd probably store the data as JSON instead of raw JavaScript. In this case, if we're just storing the data as actual JavaScript anyway, I think I like keeping it in the same file because it's easier to scroll up and look at, and the fewer files makes data transfer between the server and browser faster in HTTP/1.1

There are still some ways you can improve, but I think it's really obvious you know well what you're doing, so I'm gonna be super picky. Keep in mind while reading this that I'm being super picky, and a lot of what I'm saying is greatly a matter of preference, and your code looks well above-average as-is

  • The only thing I see that would affect your code's validity is that I don't see the html variable declared anywhere. You use it a couple times at the bottom of the file, but you never declare it with the const, let, or var keywords. It appears to be a constant once it's assigned, so I'd declare it like this:
const html = printList(students);

From this point on, everything I say is a matter of preference/style, and doesn't actually affect how your code functions

  • Each object in the students array represents a single student. Currently, the Student property hold's the student's name, but the object it's defined on already represents the student, so I think it'd be clearer if this property was called name

  • The convention in JavaScript is to store property names as camel-case characters, so I think it would've been nicer to write your objects in camel case and uppercase them when you're displaying them, like this:

{
    name: 'Tom', 
    track: 'iOS',
    achievements: 4,
    points: 9000
  }

// This makes a new function that every string has that just capitalizes the first letter

String.prototype.capitalized = function(){
    return this.charAt(0).toUpperCase() + this.slice(1);
};

// Later on when you're displaying this...
listHTML += '<h2>' + prop.capitalized() + ': ' + students[I][prop] + '</h2></p>';
  • I'd use const instead of let for students,outputDiv, and prop. In all of these cases, you're never reassigning to that variable directly. They're all constant in your code, so it's best to represent that by using const instead of let. Note that I would still use let for listHTML because you are directly assigning to that with the += operator, which means it's not constant and is, in fact, a variable

  • The formatting of your function declarations is inconsistent. As far as formatting is concerned, what matters most is that they all look the same, but my personal preference for formatting looks like this:

function myFunction(someParameter){
  • return is a keyword, not a function, but it's called like a function in your code. I'd personally write it without the parentheses, like this:
return listHTML;
  • Right now, you're concatenating your strings by adding them all together, but when you have a few variables in the middle of your string, this can get hard to read and type fairly quickly. Instead, I'd use a JavaScript template literal, which effectively pastes the value of an expression in your string where you want it to be, like this:
listHTML += `<p>${prop}: ${students[i][prop]}</p>`;
  • Currently, you wrap the student's name in a p tag, but you don't need that, since you're already specifying that it's an h2. It'd be better to use just the h2 and not the p

  • Right now, the student's name only gets printed before all of its properties because the Student key is always defined first in each object. Objects are unordered, however, so it's not good to rely on its implicit order. I'd explicitly print the student's name first and then skip it in the loop when it comes up

  • You're displaying a list of students, but you're writing them to the DOM with just p and h2 tags. In other words, the HTML doesn't realize that you're displaying a list. I'd wrap your whole student list in a ul, and then each individual list of a student's properties in another ul

  • To loop over all the students, you're currently using a C-style for loop, but JavaScript has a built-in construct for looping over every item in an array, which is the for of loop. All in all, I'd write your printList function like this (note that I'm using some things that I touched on in previous bullet points):

function printList(classList){
    let listHTML = "<ul>"; // We're making a big list, so I'd start with with a ul instead of a p
    for(const student of students){ // for of here for an array, with const because you're never changing the student
        listHTML += `<li><h2>Student: ${student.name}</h2><ul>`;
        for(const prop in student){ // for in here for an object, with const because you're never changing prop
            if(prop !== "name"){ // We already displayed the name, so we don't wanna display it again
                listHTML += `<li>${prop.capitalized()}: ${student[prop]}</li>`;
            }
        }
        listHTML += "</ul></li>"; // We've finished the student list, so we need to close it off
    }
    listHTML += "</ul>"; // We've also finished the list of all students, so we need to close it off, too
    return listHTML;
}

Like I said, I was being super picky with all of this, and you've written a bunch of amazing code so far. Awesome job!

Steven Parker
Steven Parker
230,995 Points

Using the two separate files is covered earlier in this same video. And the functional difference in your solution will not be seen when the student data is consistent.

But if a property is missing from a student, the video solution will still show the property name and list "undefined" for the value. Your method would just omit the line entirely.

And if an extra property were added (or one was misspelled), the video solution would ignore it but yours would include it in the listing.

So the distinction makes neither choice right or wrong, it's just about what behavior is desired for irregular records.

Finally, one other minor issue is that the paragraph (p) is not needed around the h2 heading element. But great job overall, keep up the good work!

Thanks guys. I walked away, calmed down and thought about it, and I think what made me nervous was that up until the last couple challenges, my solutions would be largely the same as the instructor's. Perhaps this is because the more complex the coding gets, the more solutions are available. I guess the more beginner-friendly solution videos being the same as my solutions led me to believe that coding is far more black-and-white than it actually is, and that there are predefined "correct" ways to solve them. I think I'm being too much of a perfectionist in thinking that programs with this amount of complexity are still either "correct" or "incorrect" in the way they are written so I thought I was completely on the wrong track when I saw how different the solution was.

Michael Hulet
Michael Hulet
47,912 Points

There's no single right way to do just about anything with software. Ultimately, what counts most is if it works and you can understand why. You can argue some ways are better than others, but beyond that, it's more art than science tbh. You're doing a really awesome job so far

Steven Parker
Steven Parker
230,995 Points

One of Parker's Principles of Programming is "The more complex the task, the more ways there will be to arrive at a solution". :wink: Happy coding!