JS Objects, Prototypes, and Classes Simplified
Tags: javascript, webdev, codenewbie
Published: 2020-12-19 00:22:13

In this series, you will know what Objects are, how to create and use them, understand Prototypes and Inheritance, and finally working with Classes.

# Objects
Let's begin with an intro about objects from [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects):
> JavaScript is designed on a simple object-based paradigm. An object is a collection of properties, and a property is an association between a name (or key) and a value. A property's value can be a function, in which case the property is known as a method.

A car is a simple example of an object, it has properties like brand name, model, color, condition, and methods like move forward, move backward, etc.
All of these properties are what define car characteristics as an object.

## **Creating Objects**
Objects can be created in different ways using:
- Object literal.
- Constructor function.
- Class

### Object Literal
Simply declare a variable and assign its value to {}, and between these curly braces we add the properties in a key value pairs where key must be a string and value can be of any type e.g.
```javascript
let person = {
  firstName: 'Waseem',
  lastName: 'Mansour',
  age: 36,
  isMarried: true,
  fullName: function() {
    return `${this.firstName} ${this.lastName}`;
  }
}
```

Now you can access any of the object's properties by its key name, using Dot Notation or Bracket Notation, in some cases with bracket notation only. Let's see how

```javascript
// Dot Notation: 
// Object name followed by DOT followed by property name.
console.log(person.firstName); // => Waseem
console.log(person.fullName()); // => Waseem Mansour

// Bracket Notation: 
// Object name followed by [] and property name passed between
// brackets wrapped with single or double quotes
console.log(person['firstName']); // => Waseem 

// We can use a variable that holds value of property name
// Only Bracket notation valid when passing variables
let userAge = 'age';
console.log(person[userAge]); // => 36 

// Property name string that includes space, can't be accessed
// using Dot notation, so we use Bracket notation instead.
console.log(car.brand name); // Throw Error => Uncaught SyntaxError
console.log(car['brand name']); // => BMW

// Accessing nested properties
console.log(person.address.city); // => Alexandria
console.log(person['address']['city']; // => Alexandria
```

Due to the dynamic nature of JavaScript, we can add properties to object after creation.
```javascript
let movieStar = {
  name: 'Tom Hanks',
}

movieStar.age = 64
console.log(movieStar.age); // => 64
```
Now let's assume we have another person e.g. Sara, and we will create another object to hold its information as we did before.

```javascript
let personTwo = {
  firstName: "Sara",
  lastName: "Badr",
  age: 22,
  isMarried: false,
  fullName: function() {
    return `${this.firstName} ${this.lastName}`;
  }
}
```
You must have noticed that there's a repetition in both object's structure, and we only have two objects, what if we have 50 or maybe 1000 person objects more to be created. There's must be a way to optimize our code, and apply [DRY principle](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).

### Constructor Functions
The constructor Function's syntax is like any regular function, but with tiny differences, let's take a look at how to make a constructor function to help us create Person Objects that shares the same properties and methods:

```javascript
// 1- Function name convention is to Capitalize first letter
function Person() {
  // properties to be assigned here. will leave it empty for now
}

// 2- Function execution must be preceded by "new" keyword
let waseem = new Person();

// What Happens under the hood:
// - "new" creates an empty object {}
// - "this" generated for us from function execution context
//   changed what it points to, to the new empty object created.
// - This function should not have a return statement
//   because it implicitly returns that object created
//   with all properties it may be attached to in function body.
console.log(waseem); // => Person {}

// Let's create the Person object properly now.
function Person(firstName, lastName, age, isMarried) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
  this.isMarried = isMarried;
}

// Create our person objects using Person constructor function
let waseem = new Person('Waseem', 'Mansour', 36, true);
let sara = new Person('Sara', 'Badr', 22, false);
console.log(waseem); 
//=> Person {firstName: "Waseem", lastName: "Mansour",
//   age: 36, isMarried: true}
console.log(sara); 
//=> Person {firstName: "Sara", lastName: "Badr",
//   age: 22, isMarried: false}
``` 
> You may have noticed that I didn't add the fullName method to the Person constructor function, this was on purpose, I'll explain why in my next post of this series.

Hopefully, you should have learned a lot about Objects so far.
This is my first post on DEV.to, hope you found it informative and to the point.

Thanks for reading.