# Object-ception

## Lesson objectives

*After this lesson students will be able to:*

1. Use an array inside an object
2. Iterate over an array that is within an object
3. Use an object within an object
4. Use an object within an object within an object
5. Use an array within an object within an object within an object
6. Use an array of objects
7. Use variables to store a key
8. Loop over an object

## Use an array inside an object

Let's model an adventurer who has belongings (a list)

```javascript
const adventurer = {
    name: "Timothy",
    hitpoints: 10,
    belongings: ["sword", "potion", "Tums"]
}
```

Access all values in the player.belongings array:

```javascript
console.log(adventurer.belongings)
```

Access a specific item in the belongings array:

```javascript
console.log(adventurer.belongings[0])
```

## Iterate over an array that is within an object

```javascript
for (let i=0; i < adventurer.belongings.length; i++) {
    console.log(adventurer.belongings[i]);
}
```

### Activity

* Write an object for an `adventurer` and give the adventurer some belongings
* Access the belongings array and print the last element to the console
* Use `.push()` to add a "Vogue Magazine" to the belongings array
* Write a *for* loop that prints each element in the belongings array to the console

## Use an object within an object

Our adventurer now has a companion! Our companion, a **bat**, is an object with its own properties.

Add the `companion` object to the `adventurer` object:

```javascript
const adventurer = {
    name: "Timothy",
    hitpoints: 10,
    belongings: ["sword", "potion", "Tums"],
    companion: {
        name: "Velma",
        type: "Bat"
    }
}
```

Access the companion object:

```javascript
console.log(adventurer.companion)
```

> \=> { name: "Velma", type: "Bat" }

Access the companion's name:

```javascript
console.log(adventurer.companion.name)
```

> \=> "Velma"

Access the companion's type:

```javascript
console.log(adventurer.companion.type)
```

> \=> "Bat"

### Activity (3 min)

* Write the companion object into the adventurer object
* Print just the companion's name to the console
* Change the companion's name "Velma" to "Susan"
* Console.log to check that the name was changed
* Add another object to the `adventurer` object called `companion2`.
* `companion2` should have a name and a type "Insect"

## Use an object within an object within an object

Velma the bat also has a companion, a magical **parasite** called Tim.

Let's add **Tim** to our data:

```javascript
const adventurer = {
    name: "Timothy",
    hitpoints: 10,
    belongings: ["sword", "potion", "Tums"],
    companion: {
        name: "Velma",
        type: "Bat"
        companion: {
            name: "Tim",
            type: "Parasite"
        }  
    }
}
```

**What would you write to:**

* console.log Tim's **type**

## Use an array within an object within an object within an object

Tim has a **bag of holding** and can carry an infinite number of belongings.

Let's add an array of belongings to Tim:

```javascript
const adventurer = {
    name: 'Timothy',
    hitpoints: 10,
    belongings: ["sword", "potion", "Tums"],
    companion: {
        name: "Velma",
        type: "Bat",
        companion: {
            name: "Tim",
            type: "Parasite",
            belongings: ["SCUBA tank", "Rogan josh", "health insurance"]
        }  
    }
}
```

**What would be the code to access:**

* console.log "health insurance"

## Use an array of objects

A common pattern you will start to see everywhere (especially in Unit 2 and onwards) is an **array of objects**.

An array of objects can look like this:

```javascript
const movies = [ { title: "Tokyo Story" },  { title: "Paul Blart: Mall Cop" }, { title: "L'Avventura" } ];
```

These objects have no names, they are just anonymous objects packed into an array.

You could reference them with indexes as usual:

```javascript
console.log(movies[0]);
```

You could reference the properties by first asking for the index, then the property:

```javascript
console.log(movies[0].title);
```

You could loop over the array and just print all of the titles:

```javascript
for (let i=0; i < movies.length; i++) {
    console.log(movies[i].title);
}
```

## Use variables to store a key

```javascript
const monster =  {
    name: 'Slimer',
    age: 6
}

const someVar = 'name';

console.log(monster[someVar]);  // same as monster['name'];
```

> \=> 'Slimer'

## Loop over an object

There are two way to loop over objects. You can use either way. Both ways involve looping over the object's **keys**.

Let's say we have a movie object:

```javascript
const movie = { title: "L'Avventura", director: "Michelangelo Antonioni", year: 1960 }
```

### `for ... in` loop

Print each key:

```javascript
for (let key in movie) {
    console.log(key);
}
```

> \=>
>
> title
>
> director
>
> year

Print each value:

To do this, use the key as a **variable** within the square brackets.

```javascript
for (let key in movie) {
    console.log(movie[key]);
}
```

> \=>
>
> L'Avventura
>
> Michelangelo Antonioni
>
> 1960

### `Object.keys()`

Object.keys() will return an **array of keys**

```javascript
console.log(Object.keys(movie));
```

> \=> \[ 'title', 'director', 'year' ]

To print the values, use the key as a **variable** within square brackets.

```javascript
const keys = Object.keys(movie);

for (let i=0; i < keys.length; i++) {
    console.log(movie[keys[i]]);
}
```

### Activity

Given the following movie:

```javascript
const movie = { title: "Eraserhead", director: "David Lynch", year: 1978 }
```

* Use a **for..in** loop to print all the keys of the movie object
* Use a **for..in** loop to print all the values of the movie object

#### Advanced

With the following array of movie objects:

```javascript
const movies = [
    { title: "L'Avventura", director: "Michelangelo Antonioni", year: 1960 },
    { title: "Eraserhead", director: "David Lynch", year: 1978 },
    { title: "Dayereh", director: "Jafar Panahi", year: 2000 },
    { title: "Dayereh", director: "Jafar Panahi", year: 2000 }
]
```

Create an empty object and assign it to a `moviesObj` variable. Leverage the fact that Keys are unique in an object. Loop over the movies array and add the movie titles as keys in the `moviesObj` object. This will consequently omit the duplicate movie. At the same time, give each movie key the value of an object containing the director and year. The final object should look like this:

```javascript
{
    "L'Avventura": { director: "Michelangelo Antonioni", year: 1960 },
    "Eraserhead": { director: "David Lynch", year: 1978 },
    "Dayereh": { director: "Jafar Panahi", year: 2000 }
}
```

*Tip:* You might want to use this technique for the hardest part of tonight's homework.

* Use **Object.keys** loop to print all the values of the movie object.

*This lesson was adapted from* [*SEI-MAE*](https://git.generalassemb.ly/Software-Engineering-Immersive-Remote/SEIR-MAE-INSTRUCTORS/blob/master/unit_1/w03d3/instructor_notes/1.%20Object-ception.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tmdarneille.gitbook.io/seirfx/javascript/objects/object-ception.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
