JavaScript Express Basics Parameters, Query Strings, and Modularizing Routes Card Template

Tiffany Hsieh
Tiffany Hsieh
3,627 Points

Why is the "hint" value defined as `cards[id]`?

The hint object is defined as cards[id] , but doesn't this reference the entire object within the array? For example, when I do console.log(cards[0]) , the following is printed:

{ question: 'What is one way a website can store data in a user\'s browser?',
  hint: 'They are delicious with milk',
  answer: 'Cookies' }
router.get('/:id', (req, res) => {
    const {side} = req.query;//question or answer
    const {id} = req.params;//the # card
    const text = cards[id][side];//text of the question or answer
    const {hint} = cards[id];//hint?.......
    const templateData = {text, hint};

    res.render('card', templateData);
});

However, when I do console.log(hint) with the following code, to the url http://localhost:3000/cards/0?side=question, it only prints the hint:

Hint: It starts with a "J"

How does cards[id] know to only print the hint attribute? Also, changing the {hint} definition to cards[id].hint makes the hint disappear on the webpage. Why doesn't this work?

1 Answer

andren
andren
28,375 Points

That is an example of Object destructuring which is a feature added in JavaScript ES6.

If you look at the constants being defined you probably notice that the name of some of them are enclosed in curly braces {} and some are not. Those curly braces are how you indicate that you want to do object destructuring rather than normal assignment.

When you do object destructuring you are telling JavaScript that you want it to take the constant you specify and set it equal to a property in the object that matches its name.

Let's say you had an object like this:

exampleObj = {
  message: "Hello World"
  number: 20
}

If you wanted to pull the two properties into their own constants you would normally do it like this:

const message = exampleObj.message;
const number = exampleObj.number;

However isn't that a bit redundant? You are repeating the name of the property, and if you wanted to pull out a lot of properties you would have a lot of lines with a lot of duplicated names.

With object destructuring you can simply that like this:

const {message} = exampleObj;
const {number} = exampleObj;

JavaScript will look at the name of the constant (this will also work with normal variables of course) and then pull out a property with a matching name from the object. But that is not all, if you are pulling out multiple properties from one object you can combine the assignments into one statement. Like this:

const {message, number} = exampleObj;

That produces the exact same constants as the previous code example. Now with only two properties that's only saving one line of code. But if you were pulling out a dozen properties for example, then object destructuring would save you a lot of typing. And arguably make the code look a lot cleaner.

Tiffany Hsieh
Tiffany Hsieh
3,627 Points

Thank you! This was a great explanation and cleared up all of my questions

andren
andren
28,375 Points

Good to hear, I'm glad I could be of help.

By the way while you did not ask about it I just noticed that one of those constants:

const templateData = {text, hint};

Also use a ES6 feature which you might not be familiar with.

It is in some sense a reverse version of object destructuring. It is creating an object by just specifying the property names. This is a shorthand where if you only specify the property name JavaScript will look for a variable matching that name, and if found it will set that variable as the value for the property.

Meaning that the above code is equivalent to this code:

const templateData = {
  text: text,
  hint: hint
};

Where text and hint are existing variables that exists outside the object. You can mix shorthand properties and regular explicit properties in the same object declaration.

I apologize if you already knew this, but I wanted to clarify it for completeness sake.