Object Oriented Programming: Working With Classes in JavaScript.
Tags: javascript, tldrnotes
Published: 2022-12-28 04:40:32

### Introduction:

This is by no means an exhaustive guide to Object Oriented Programming in Javascript. These notes on OOP in JavaScript are what I mostly use, and come back to them daily for reference.

On this note, I primarily focus on creating objects with `class` and `function` keywords. I also talk about `inheritance` method chaining and some other stuff. For a detailed explanation and examples, please visit the MDN's blog here on [classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).

### Object Oriented Programming

#### Object Example

* An Object in JavaScript is a collection of properties. Property can be functions (function has an action associated with it) or a simple `key` :`value` pair which could just represent a feature of the object it is in. For example: `color: red` is a property whereas `function accelerate(){}` is a property of the car that has some action associated with it.
    
    * For example,
        

```js

const car = {
	color: red,
	type: sedan, 
	accelerate: function(){
		// code here
	}
}
```

> Please Note: I have assigned the object above to a variable called car. If you don't need to refer back to the object, you don't need to assign the object to a variable.

#### Creating Objects: Object Literal

* Also known as object initializers, object literals allow us to create Javascript objects. We need to use curly braces in JavaScript to initialize the object.
    

```js
// empty object
let obj = {} 

// object with property and value
let user = {
	name: 'John Doe', // property can be identifies
	1000: 'example_1', // or property can be a number 
	"email": 'john.doe@useremail.com', // or it can be a string. 	
	login: function(){} 
	logout(){} // ES6 syntax. 
}
```

* In the `user` the object above, we have encapsulated or gathered all the relevant properties of a user in one place. Think of opening and closing curly braces `{}` as a capsule that groups all the relevant properties of user.
    

#### Accessing and Updating Properties

##### **Accessing Object Properties**

* To access object properties we can use simple dot notation.
    

```js

console.log(user.email) 
// expected output: john.doe@useremail.com
```

* However, dot notation only works when the object has an identifier that starts with a `letter`, `$,` `_` or `unicode` escape sequence. So, to access the property of type number you need to use the following syntax.
    

```js

console.log(user[1000]) // expected output: example_1 

// this notation below works for other properties as well. 

console.log(user['email']) // expected output: john.doe@useremail.com
```

* We can access the properties of objects dynamically as well.
    

```js

let foo = 'email'
console.log(user[foo]) // expected output: john.doe@useremail.com
// changing the variable 
let foo = 'name'
console.log(user[foo]) // expected output: John Doe
```

##### **Updating Object Properties**

* To update the property, simply `get` the property name and `set` it to new value. For example, for our user object, we can do the following.
    

```js

user[1000] = "example_2"; 
user.email = "email@johndoe.com";
```

* Setting a property that does not exist on the object:
    

```js

user.race = 'South Asian' 
console.log(user) // expected output contains: {.... race: "South Asian"}
```

#### Class and Constructor Function: Creating Multiple Objects With the Same Property

* You might have to create multiple objects with the same property types, just like creating multiple computers or cars with the same features (property).
    
* First, create a constructor class (blueprint) of the object.
    

```js
class Car {
	constructor(color, type, accelerateFn){
		this.color = color;
		this.type = type;
		this.accelerate = function(){console.log(accelerateFn)};
	}
}
```

> `this` represents the object it is in. When we create a new object (example: `whiteCar`) with the blueprint above, `this` keyword will represent the object just created (whiteCar)

* Also, there can only be one method with the name `constructor` inside the Class.
    

Now to create a new object with all these properties of the constructor class, do the following.

```js
const whiteCar = new Car('white','hatchback','is a fast car')
console.log(whiteCar.color) // expected output: white

const redCar = new Car('red', 'sedan', 'is slower car')
console.log(redCar.color) // expected output: red
```

##### **Methods:**

* For the example above: we can add methods `brake` and `headlights` like this
    

```js

class Car {
	constructor(color, type, accelerateFn){
		this.color = color;
		this.type = type;
		this.accelerate = function(){console.log(accelerateFn)};
	}
	// methods
	brake(){
		console.log(`Brake of this ${this.color} ${this.type} is in            good condition.`)
          return this;
	}

	headLights(){
		console.log(`Lights of this ${this.color} ${this.type} is in        good condition.`)
          return this;
	}
	
}
```

* If you want the `methods` or `properties` to not be shared with another object/instance created from the class, use the word `static`
    

```js

class Car {
	constructor(color, type, accelerateFn){
		this.color = color;
		this.type = type;
		this.accelerate = function(){console.log(accelerateFn)};
	}
	// methods
	brake(){
		console.log(`Brake of this ${this.color} ${this.type} is in good condition.`)
          return this;
	}
	headLights(){
		console.log(`Lights of this ${this.color} ${this.type} is in good condition.`)
          return this;
	}
	// static example: 
	static moto = 'Let\'s make the world a better place'
	static hello(){
		console.log(`This method is only available in this Car Object`)
	}
}
```

##### **Method Chaining.**

* `return this` in the above object, methods return the object it is in. What that allows us to do is call all the methods of the object after one another.  
    For example,
    

```js

const redCar = new Car('red','sedan','is faster')
console.log(redCar.brake().headLights())
```

Here, we can call `headlights()` after `brake()`.

#### Class Inheritance

* If you want to create a new object with all the properties of the previous one plus some more properties and methods of its own, you need to inherit the properties of the previous object with class Inheritance.
    

```js

class SuperCar extends Car {
	launchMode(){
		console.log(`Launch Mode of ${this.color} supercar`)
	}
}
```

* Now when you create a new `SuperCar`, you need to do this
    

```js

const ferrari = new SuperCar('red','super-car','is fastest')
```

> Note: The new object that extends on properties of another object expects all the arguments of the previous one. Therefore, in this example above, we need to provide in `color`, `type` and `accelerateFn`

#### Emulating Class with `function` Keyword

* The following code with `function` keyword is also valid
    

```js

function Car(color, type, accelerateFn){
	this.color = color;
	this.type = type;
	this.accelerate = function(){console.log(accelerateFn)};
}

// to attach methods, we can use prototype

Car.prototype.brake = function(){
	console.log(/*code here*/)
}
```

Now, an instance of the object can just call in the method

```js

const ferrari = new SuperCar('red','super-car','is fastest') 
ferrari.brake();  // works. :)
```

##### **Inheritance of class created with the function keyword**

* To create a new Object from the original object (with constructor function) created with `function()` keyword, do this.
    

```js

function SuperCar(...args) {
	Car.apply(this, arg)
}
// here, ...args is taking arguments of Car and making them an array.
```

Now, you can create an object like this

```js

new lambo = new SuperCar('red','superCar','is fastest') // with all the same args
```

* To inherit the prototype methods attached to the original object created with `function()` keyword, use `Object.create()` like so.
    

```js

SuperCar.prototype = Object.create(Car.prototype) // now all the prototype functions appear for SuperCar object as well.
```

**Important Note:**

* An Important difference between `funciton decleration` and `class decleration` is that while functions can be called before they are defined but classes can't.
    

```js

const ferrari = new SuperCar() 
class SuperCar = {}

// Refrence Error because we are calling function before creating it. 
```