🔥Object in JavaScript : The Only guide that you need
Tags: javascript, webdev, programming, tutorial
Published: 2023-07-04 17:59:55

> JavaScript's Objects are fundamentally different in how they behave from any object in other Object Oriented language( C++, Java etc ). Some developers skip this part but it is a important part of language that we should be aware of.

## Table Of Contents
- <a href='#thisid1'>1. What is Object in JS</a>
- <a href='#thisid2'>2. Property v/s Method</a>
- <a href='#thisid3'>3. Property Descriptors</a>
- <a href='#thisid4'>4. Writable Descriptors</a>
- <a href='#thisid5'>5. Enumerable Descriptor</a>
- <a href='#thisid6'>6. Immutability</a>
- <a href='#thisid7'>7. Implementing Iterator to traverse Oject</a>

---
<h2 id='thisid1'>1. <u>What is Object in JS?</u></h2>

The Object is one of JavaScript's data types. It is used to store data in key-value pairs. We can add properties to object using the '.' operator or '.defineProperty()' method. We can use 'delete' operator to remove any property from the objects.

```js
var obj = {};
obj.a = 4;

console.log(obj.a); // 4
delete obj.a;
console.log(obj.a) // undefined :- as property not found
```
`NOTE :- The 'delete' operator only remove the property from object, it doesn't free memory`

**How do we create a object ?**
Objects can be created in one of the following ways :-
1. Literal Form
2. Constructed form ( Using the Object() constructor ) 

```javascript
// literal form
var obj1 = {
    a : 2,
    b : 3
};

// constructed form
var obj2 = new Object();
obj2.a = 3;
obj2.b = 4;
```

**Built-in Objects.**
```
1. String                5. Function
2. Number                6. Array
3. Boolean               7. RegEx
4. Object                8. Error
5. Date
```
Above given are actually built-in function constructors which can be used to create objects using 'new' operator. 
`NOTE :- Functions and Arrays are also objects in JS and 'null' is not a object, rather it is a primitive type in Js.`

```js
let arr = [1,2,'text'];
arr.say = 'i am a array ojbect';

function fun(){
    console.log('hello world');
}
fun.say = 'i am a function object';

console.log(arr.say); // i am a array object
console.log(fun.say); // i am a function object

// The only way we could add properties to the function 
// and array was because they were objects
```
`WARNING :- Although, properties can be added to functions and arrays this should be avoided.`
Don't rely on 'typeof' operator as it can give wrong results. 

```js
let arr = [1,2,'text'];

function fun(){
    console.log('hello world');
}

var b = null;

console.log(typeof arr); // object
console.log(typeof fun); // function insted of object
console.log(typeof b);  // object instead of null

// These mistakes in JS are not fixed as they would 
// break the internet and websites which depend on 
// this functionality might stop working

// to check for null we can use '==='
console.log(b===null); // true
```

---
<h2 id='thisid2'>2. <u>Property v/s Methods.</u></h2>

Methods are functions which can be only accessed by the objects. But functions in JS are not owned by any object, they only contain the reference of the function inside of them. So,  functions inside objects are merely just another 'property' not 'method'. Generally they can be used interchangeably but always remember there is a slight difference.

```js
var obj = {
    fun : function(){
        console.log('hello world')
    }
};

var newFun = obj.fun; // reference of fun is passed
newFun(); // hello world
// 'fun' function is called without the need of 'obj' object
```
---
<h2 id='thisid3'>3. <u>Property Descriptors</u></h2>

As the name suggests, it give description of object's property. There are 4 basic properties :

1. value : value of the property
2. writable : if the value can be changed
3. enumerable   : if the property is visible for iteration (loops).
4. configurable : if the description can be changed

writable,enumerable and configurable are boolean value.

`NOTE :- (configurable : false) prevents delete operator from removing the property from object. `

```js
var obj = {};

// used to add property to a object
Object.defineProperty(obj,'a',{ // -> only string value of key is passed
    value : 2,
    enumerable : true,
    configurable : true,
    writable : true
});
console.log(obj.a); // 2 

// used to get the description of property
console.log(Object.getOwnPropertyDescriptor(obj,'a'));
```

---
<h2 id='thisid4'>4. <u>Writable Descriptor</u></h2>
Writable descriptor is a boolean value which tells us if the value can be changed or not.
`NOTE :- Even when writable is false Ojbect.defineProperty() can change the value of property but '.' operator can't.`

```js
var obj = { a : 2 };

Object.defineProperty(obj,'a',{
    writable : false,
});
obj.a = 8;
console.log(obj.a); 
// 2 -> value not changed by '.operator'

Object.defineProperty(obj,'a',{
    value : 5,
});

console.log(obj.a); 
// 5 -> value changed by Ojbect.defineProperty
```
---
<h2 id='thisid5'>5. <u>Enumerable Descriptor</u></h2>

Enumerable Descriptor is a boolean value which tell if the property should be visible during iteration.

Setting the enumerable descriptor to false, prevents the property from being accessed during iteration but can be accessed using the '.' operator.

```js
var obj = {
    a : 2,
    b : 3,
    c : 4
};

Object.defineProperty(obj,'a',{
    enumerable : false,
});

// This loop doesn't iterate over 'a'
for (const key in obj) {
    console.log(`key : ${key} value : ${ obj[key] }`);
}
// Object.keys() returns array of keys
// it also doesn't iterate over 'a'
console.log(obj); // [ 'b','c' ]

// although it can be accessed using '.' operator
console.log(obj.a);
```

---
<h2 id='thisid6'>6. <u>Immutability</u></h2>
An immutable value is one whose content cannot be changed. This is very useful in JavaScript as this can be used to store state of application. Only when entirely new object is created we say that the state has changed. 
We can only implement shallow component. This means that if the property is an object then its reference would be immutable not it's content.

There are 4 levels of immutability in JS : 

**1-> Object Constant**
  - writable false + configurable false
  - The property value can't be changed, redifined or deleted

**2-> Prevent Extension**
  - New properties can't be added
  - Setting new property fails silently but in _strict mode_ it throws an error

```js
var obj = { a : 2 };
Object.preventExtension( obj );
obj.b = 4; // throws error in strict mode
```
**3-> Seal**
  - preventExtension() + configurable false
  - New properties can't be added
  - Existing properties can't be removed but value can be changed

```js
var obj = {
    a : 2,
    b : 3,
    c : 4
};

Object.seal(obj);
obj.d = 100; // throws error in strict mode 
console.log(obj.d);
```
**4-> Freeze**
  - seal() + writable false
  - no properties can be added, deleted or removed
  - existing properties' value can't be changed

```js
var obj = {
    a : 2,
    b : 3,
    c : 4
};
Object.freeze(obj);
```

---

<h2 id='thisid7'>7. <u>Implementing iterator</u></h2>
Now, let us apply all that we have learnt by implementing a iterator.
**What exactly is iterator?**
Iterator is object which is used to traverse a sequence. The sequence could be the properties of object or index of array. It provides us with a function 'next' which when called returns object with two properties :-
- value -> value of current index
- done -> tells us if we have traversed the whole array
Every time 'next' is called it increments the iterator to point at next element in the sequence.

```js
let obj = {
    a : 2,
    b : 4,
    c : 5
}

Object.defineProperty(obj,'my_iterator',{
    writable : false,
    enumerable : false,
    configurable : false,
    value : function(){
        var self = this;
        var idx = 0;
        var ks = Object.keys(self);

        return {
            next : function(){
                return {
                    value : self[ks[idx++]],
                    done : (idx>ks.length)
                }
            }
        }
    }
});

var it = obj['my_iterator']();
console.log(it.next()); // value : 2, done : false
console.log(it.next()); // value : 4, done : false
console.log(it.next()); // value : 5, done : false
console.log(it.next()); // value : undefined, done : true
```
`NOTE :- If you want to overwrite the internal implementation of iterator then use Symbol.iterator as key instead of my_iterator`

---
That is it for this blog. If you liked this blog then please like and share. If I made a mistake in this blog then please comment I would surely get back to it.
I am planning to write more blogs like this, so stay tuned.