Back to JS Basics: Objects 
Tags: javascript, beginners, webdev
Published: 2020-10-11 21:29:03

*This is a part of my series of notes as I revisit core JS concepts.*

### Concepts covered:

- General **object literals** overview
- Dot notation vs Bracket notation
- Object References & Cloning

Constructor functions are **not** covered in this article.

In my last article, I had gone into the details of primitive data types in JS. This time it is the other data type in JS - objects. 

As opposed to the primitive types, objects are used to store more complex entities - generally, a collection of related properties or methods.

A property is a “key: value” pair, where key is a string, and value can be anything (including array). A method is when the value is a function.

```jsx
const user = {
name: 'Poulami',
handle: 'poulamic',
interests: ['UX', 'front-end', 'generative art'],
greet: function() {
    alert(`Hi! I'm ${this.name}.`);
  }
}
```



### Some things to keep in mind:

- An object declared as `const` can be **modified**. It isn't possible to reassign 'user'
```jsx
const user = {
name: 'Poulami',
handle: 'poulamic',
interests: ['UX', 'front-end', 'generative art'],
greet: function() {
    console.log(`Hi! I'm ${this.name}.`);
  }
}
user.greet(); // Hi! I'm Poulami.

user.name = "Unknown"
user.greet(); // Hi! I'm Unknown.

user = {
name: 'Unknown',
handle: 'poulamic',
interests: ['UX', 'front-end', 'generative art'],
greet: function() {
    console.log(`Hi! I'm ${this.name}.`);
  }
}
// Uncaught TypeError
```

- There is no limitation to what key variable name can be (including 'let', 'return', etc.). Except for a variable named `_proto_` that has to be of type 'object'. (This is related to prototype, not included in this article)

- There will be no error if we try to access a property that doesn’t exist - it will return 'undefined'.
To check if the property exists , we can use the `in` operator- it returns true if the specified property is in the object

```jsx
user.age // undefined
'age' in user //false
```



### Dot notation vs Bracket notation

There are two ways to access object properties - using dot notation, and using bracket notation.

```jsx
//Get
user.name
user['name']

//Set
user.name = "Unknown"
user['name']= "Unknown"
```

Both essentially work in the same way, except in some cases where bracket notation is the only one which works.

- Using variables for key name 

```jsx
let requested = "handle";
console.log(user.requested) //undefined
console.log(user[requested]) //poulamic
```

- Multiword property names 

```jsx
const user = {
name: 'Poulami',
handle: 'poulamic',
interests: ['UX', 'front-end', 'generative art'],
"has published" : true, //multiword keys are in quotes
greet: function() {
    console.log(`Hi! I'm ${this.name}.`);
  }
}

user["has published"] // true
```

Within the object literal, square bracket is used for computed properties - i.e. while creating the literal, we set a property name through a variable; 

```jsx
let social = "twitter";
const user = {
name: 'Poulami',
handle: 'poulamic',
interests: ['UX', 'front-end', 'generative art'],
"has published" : true,
[`${social}account`]: true,
greet: function() {
    console.log(`Hi! I'm ${this.name}.`);
  }
}
console.log(user.twitteraccount) // true
```
<br/>



### Object References & Cloning

Primitives and objects behave differently when a variable is assigned a value through (equating with) a variable name. 

```jsx
let a = 5;
let b = a;
```

The expectation is that we have **two independent variables** 'a' & 'b' - both with value of 5. And that's true - when the value is of a primitive data type. (Under the hood, they are two different spots in memory).

```jsx
let p = "poulami";
let q = p;
console.log(p,q) // poulami poulami
q= "unknown"
console.log(p,q) // poulami unknown
```

But it isn't so in case of objects. In case of objects, the actual object is stored somewhere in memory and the variable has a “reference” to it.

```jsx
let user = {
name: 'Poulami',
handle: 'poulamic',
interests: ['UX', 'front-end', 'generative art'],
greet: function() {
    alert(`Hi! I'm ${this.name}.`);
  }
}

let user2 = user;
```

In this case, there are two variables, but **only one value.** The value has a point in memory & both the variables reference **the same object**. We can access the object and modify it through either variable, and changes are reflected when we try to access it through the other variable.

```jsx
let user = {
name: 'Poulami',
handle: 'poulamic',
interests: ['UX', 'front-end', 'generative art'],
greet: function() {
    alert(`Hi! I'm ${this.name}.`);
  }
}

let user2 = user;
user2.name = "unknown";
console.log(user.name,user2.name) //unknown unknown
```

We can think of it like a shared document - in case of primitives, a variable is given a duplicated copy of the sheet which they can change without affecting the original; while in objects, the var is given author permission to the same sheet.

To have an independent copy, we need to clone the array. One way is to use the `[Object.assign()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)` method. 

```jsx
let user2 =Object.assign({}, user);
user2.name = "unknown";
console.log(user.name,user2.name) //Poulami unknown
```

Seems to work! Let's try another one

```jsx
let user2 = Object.assign({}, user);
user2.name = "unknown";
user2.interests[0] = 'Design'
console.log(user2.interests) // [ "Design", "front-end", "generative art" ]
console.log(user.interests) //  [ "Design", "front-end", "generative art" ]
```

What happened?!

Well, the above method works with primitive values, but not object data types. Even within objects, nested objects (like arrays) behave as discussed above - variables are referencing to the object. So. when the (parent) object is cloned, it's the reference which is being copied.



### Shallow and deep copy

A shallow copy is one in which only one level is copied while others are still connected to the original variable (through same reference). This will mostly work fine for an object containing only primitive values.

In a deep copy, on the other hand, all the values (including nested) have their own spot in memory and disconnected from the original variable.

[This medium article](https://medium.com/javascript-in-plain-english/how-to-deep-copy-objects-and-arrays-in-javascript-7c911359b089) explains several methods to shallow/deep copy objects and arrays in JavaScript.

References:
[javascript.info](https://javascript.info/object)
[MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics)