# Understanding Objects in JavaScript

If you are working with JS and you when you have to deal with complex structured data. That’s where **Objects** come in.

## What Are Objects and Why Do We Need Them?

Imagine you want to store information about a person. Using basic variables, your code would look like this:

```javascript
let personName = "Alex";
let personAge = 25;
let personCity = "London";
```

This works, but it’s messy. These variables are floating around independently. If you add 10 more people, your code becomes a nightmare to manage.

## Object

An Object solves this by grouping related data together into a single, organized structure. Think of an object like a real-world dictionary: you look up a word (the key) to find its definition (the value).

In JavaScript, objects are collections of these **key-value pairs**.

## Array vs. Object: What’s the Difference?

You might be wondering, "Can't I just use an array?"

You can, but it’s not always the right tool for the job.

*   **Arrays** are for *ordered* lists of data. You access items using their numbered index (`array[0]`). Use arrays when the order matters (e.g., a list of top 10 movies).
    
*   **Objects** are for *labeled* data. You access items using their specific name (`object.name`). Use objects when you have a single entity with descriptive properties.
    

## Create Object

Creating an object is incredibly straightforward. We use curly braces `{}` to define it, and inside, we separate our keys and values with a colon `:`.

```javascript
const person = {
  name: "Alex",
  age: 25,
  city: "London"
};

console.log(person);
```

## Access Data inside Object

Now that we have our object, how do we read the data inside it? You have two main tools in your belt: Dot Notation and Bracket Notation.

### **Dot Notation (The everyday choice):**

This is the cleanest and most common way to grab a value.

```javascript
console.log(person.name); // Output: "Alex"
```

### **Bracket Notation (The flexible choice):**

You use brackets when your key has a space in it (which isn't recommended, but happens), or when you are using a variable to look up a key dynamically.

```javascript
console.log(person["city"]); // Output: "London"

// Dynamic lookup example:
let query = "age";
console.log(person[query]); // Output: 25
```

## Updating Object Properties

Objects are mutable, meaning you can change their data even after they are created (yes, even if you used `const`).

```javascript
// Alex had a birthday
person.age = 26; 

// Alex moved to a new city
person["city"] = "Manchester";

console.log(person.age); // Output: 26
```

## Adding and Deleting Properties

JavaScript objects are incredibly flexible. You can add new properties on the fly, or delete them if they are no longer needed.

Add

```javascript
person.profession = "Software Developer";
console.log(person.profession); // Output: "Software Developer"
```

Delete

```javascript
delete person.city;
console.log(person.city); // Output: undefined
```

## Looping Through Object Keys

Sometimes you need to read every single piece of data inside an object, but you don't know the keys in advance. To do this, we use a special loop called the `for...in` loop.

```javascript

const car = {
  brand: "Tesla",
  model: "Model 3",
  year: 2023
};

for (let key in car) {
  // We use bracket notation here because 'key' is a variable!
  console.log(`${key}: ${car[key]}`); 
}

// Output:
// brand: Tesla
// model: Model 3
// year: 2023
```

## Deep Dive in object

### All ways to create object

**The Object Literal (The Daily Driver)**

As mentioned above, this is the standard, easiest way to create an object. You will use this 95% of the time.

```javascript
const user = {
  name: "Alex",
  role: "Developer"
};
```

**The** `new Object()` **Constructor**

This uses JavaScript's built-in Object constructor. It does the exact same thing as the literal, but it's more verbose. It's rarely used in modern code.

```javascript
const user = new Object();
user.name = "Alex";
user.role = "Developer";
```

`Object.create()` **(For Prototypal Inheritance)**

This is a powerful method. It creates a brand new object, but allows you to choose an existing object to act as its "prototype" (blueprint).

```javascript
const vehiclePrototype = { wheels: 4 };
const car = Object.create(vehiclePrototype);

car.brand = "Tesla";
console.log(car.wheels); // Output: 4 (Inherited from the prototype!)
```

**Constructor Functions (The Old-School Blueprint)**

Before modern classes existed, developers used normal functions with the `new` keyword to create multiple instances of an object.

```javascript
function User(name, role) {
  this.name = name;
  this.role = role;
}
const user1 = new User("Alex", "Developer");
```

**ES6 Classes (The Modern Blueprint)**

Introduced in 2015, this provides a cleaner, more readable syntax for creating object blueprints. Under the hood, it works exactly like the Constructor Function above.

```javascript
class UserClass {
  constructor(name, role) {
    this.name = name;
    this.role = role;
  }
}
const user2 = new UserClass("Sam", "Designer");
```

### Important methods on objects

JavaScript provides a static `Object` utility with several incredibly useful methods. If you are manipulating data, you will use these constantly.

```javascript
const laptop = { brand: "Apple", model: "MacBook Pro", year: 2023 };
```

*   `Object.keys(obj)`: Returns an array of the object's keys.
    
    ```javascript
    console.log(Object.keys(laptop)); // ["brand", "model", "year"]
    ```
    
*   `Object.values(obj)`: Returns an array of the object's values.
    
    ```javascript
    console.log(Object.values(laptop)); // ["Apple", "MacBook Pro", 2023]
    ```
    
*   `Object.entries(obj)`: Returns an array of arrays, each containing a \[key, value\] pair. This is amazing for looping!
    
    ```javascript
    console.log(Object.entries(laptop)); 
    // [["brand", "Apple"], ["model", "MacBook Pro"], ["year", 2023]]
    ```
    
*   `Object.freeze(obj)`: Completely locks an object. You cannot add, delete, or change *any* properties.
    
*   `Object.seal(obj)`: Partially locks an object. You cannot add or delete properties, but you *can* update existing ones.
    

### Deep Copy vs Shallow Copy

This is a core concept that trips up almost every JavaScript developer at some point.

In JavaScript, primitive types (strings, numbers) are passed by **value**. But Objects are passed by **reference**. When you assign an object to a new variable, you aren't copying the data; you are just copying the *memory address* pointing to that data.

## The Shallow Copy

A shallow copy creates a new object and copies the *top-level* properties over. However, if your object has a nested object inside it, that nested object still shares the same memory reference!

**How to make a shallow copy:** You can use the Spread Operator (`...`) or `Object.assign()`.

```javascript
const original = {
  name: "Alex",
  skills: { language: "JavaScript" } // This is a nested object
};

// Create a shallow copy using the spread operator
const shallowCopy = { ...original };

// Let's change the top-level property
shallowCopy.name = "Sam"; 
console.log(original.name); // "Alex" (Safe! Top-level is copied)

// BUT, let's change the nested property
shallowCopy.skills.language = "TypeScript";
console.log(original.skills.language); // "TypeScript" (Wait, the original changed too?!)
```

because it was a shallow copy, both objects are sharing the exact same `skills` object in memory.

## **The Deep Copy**

A deep copy creates a completely independent clone. Every nested object is duplicated into a brand new memory space. Changing the clone will *never* affect the original.

**How to make a deep clone:**

**1\. The Modern Way:** `structuredClone()`  
This is a built-in feature in modern JavaScript (available in browsers and Node.js). It is currently the absolute best and cleanest way to deep clone an object.

**JavaScript**

```plaintext
const deepCopy = structuredClone(original);

deepCopy.skills.language = "Python";
console.log(original.skills.language); // "TypeScript" (The original is perfectly safe!)
```

**2\. The Old Hack:** `JSON.parse(JSON.stringify())`  
Before `structuredClone()` existed, developers used this trick. It converts the object into a text string, and then parses it back into a brand new object.

*   *Warning:* This method breaks if your object contains Functions, `Date` objects, or `undefined` values, as JSON doesn't support them.
    

**3\. The Library Way: Lodash**  
If you are working in a massive enterprise codebase, you might see `_.cloneDeep(obj)` from the Lodash library being used to safely handle complex cloning.
