# Understanding objects, prototypes, and classes in JavaScript

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published May 28, 2019, updated Nov 20, 2022. Topics: JavaScript.
Canonical URL: https://attacomsian.com/blog/objects-prototypes-classes-javascript

> A detailed introduction to JavaScript objects, prototypes, and classes and how to use them in modern JavaScript development.

JavaScript is based on a simple object-oriented programming model, with objects being a fundamental part of the language. Almost **everything** in JavaScript is an object. Unlike other object-oriented programming languages such as Java, JavaScript objects are **very flexible**.

## Objects

An object is a collection of key-value pairs called properties. A property's key is a string or symbol (also known as **property name**), and its value can be anything. 

There are multiple ways to [create an object](https://attacomsian.com/blog/javascript-create-object) in JavaScript. The simplest and the most popular way is to use **object literal** syntax:

```javascript
const user = {
  fisrtName: 'John',
  lastName: 'Doe',
  age: 29
}
```

Objects can also be created using the **new operator**. The `new` keyword can be used either with an in-built `Object` constructor function or a user-defined constructor function:

```javascript
// in-built constructor function
const user = new Object()
user.fisrtName = 'John'
user.lastName = 'Doe'
user.age = 29

// user-defined constructor function
function User(fisrtName, lastName, age) {
  this.fisrtName = fisrtName
  this.lastName = lastName
  this.age = age
}

const user = new User('John', 'Doe', 29)
```

A property's value can also be a function. Such a property is called a method:

```javascript
const user = {
  fisrtName: 'John',
  lastName: 'Doe',
  age: 29,
  fullName: function () {
    return `${this.fisrtName} ${this.lastName}`
  }
}
```

Properties values are accessible using both the dot (`.`) notation and the square bracket (`[]`) notation:

```javascript
// dot notation
console.log(user.fullName()) // John Doe
console.log(user.age) // 29

// square bracket notation - does not work for methods
console.log(user['fisrtName']) // John
```

You can add new properties to an existing object by just assigning them values:

```javascript
user.country = 'United States'

// method can also be added
user.ageRange = function () {
  return `${this.age - 5}-${this.age + 5}`
}
```

To remove a property from the object, use the `delete` operator:

```javascript
delete user.age
```

To iterate over all keys of an object, we can use the [`for...in`](https://attacomsian.com/blog/for-in-loop-in-javascript) loop:

```javascript
for (const key in user) {
  console.log(user[key])
}
```

The [object literal syntax](https://attacomsian.com/blog/javascript-object-property-shorthand) can only be used to create a single object. For creating multiple objects of the same type, you must use the object constructor function:

```javascript
function Animal(name, icon) {
  this.name = name
  this.icon = icon
}

const rabbit = new Animal('Rabbit', '?')
const cat = new Animal('Cat', '?')
```

We cannot directly assign values to an object constructor to add new properties and methods. New properties must be added inside the object constructor function:

```javascript
Animal.color = 'Red' // wrong way

// correct way
function Animal(name, icon, color) {
  // ...
  this.color = color
}
```

## Prototypes

All objects in JavaScript inherit properties and methods from another object called prototype. The `prototype` property allows us to add new properties and methods to existing object constructors. These properties are shared among all instances of the specified type rather than just one instance of the object. 

Let us add new properties to all objects of type  `Animal` via prototype:

```javascript
// add property
Animal.prototype.color = 'White'

// add method
Animal.prototype.meow = function () {
  if (this.name === 'Cat') {
    return `${this.name} can meow!`
  } else {
    return `${this.name} cannot meow!`
  }
}
```

Now the above `cat` and `rabbit` objects have the property `color` and method `meow()` because the `prototype` of `Animal` has them:

```javascript
console.log(cat.color) // White
console.log(rabbit.meow()) // Rabbit cannot meow!
console.log(cat.meow()) // Cat can meow!
```

If you want to access the shared `prototype` property through an instance of a specific type, there is a `__proto__` property available. You can modify the existing prototype properties or add new properties using this property. 

Since the `prototype` property is shared among all instances, changes made to one instance's `prototype` property or method will be reflected in all instances:

```javascript
cat.__proto__.color = 'Black'
cat.__proto__.eatMeat = true

console.log(rabbit.color) // Black
console.log(rabbit.eatMeat) // true
```

Similar to objects, the `prototype` property or method can be removed using the `delete` operator:

```javascript
delete cat.__proto__.eatMeat
// OR
delete Animal.prototype.eatMeat

console.log(rabbit.eatMeat) // undefined
```

As we can see above, the `prototype` property is a core part of object basics in JavaScript. Any changes to this property affect all instances of that particular object type.

## Classes

The concept of classes was introduced in JavaScript in ES6 (ECMA2015). In the object-oriented programming paradigm, a class is a blueprint for creating objects with properties and methods while encapsulating the implementation details from the user. However, the concept of true classes does not exist in JavaScript.

JavaScript classes are nothing but just syntactic sugar over existing prototype-based inheritance and constructor functions. Let us see an example:

```javascript
class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }

  sayHi() {
    return `? ${this.name}!`
  }
}
```

Now, if we want to create a new instance of the `Person` class, we must use the `new` operator:

```javascript
const bill = new Person('Bill', 25)
console.log(bill.sayHi()) // ? Bill!
```

When we create an object of the `Person` class, the class constructor does the following:

1. Create a new function named `Person` and copy all the properties declared inside the constructor into it (`name` and `age`).
2. Add all methods of the class, such as `sayHi()`, to the `Person.prototype` property.

Afterward, when we call any method of the object, it is taken from the `prototype` property. Read [this article](https://attacomsian.com/blog/javascript-classes) to learn more about JavaScript classes.

## Summary

Objects are an essential part of JavaScript language. Almost everything in JavaScript is an object.

* An object is a collection of key-value properties. An object can be created with either object literal syntax or object constructor function syntax.
*  Whenever a new function is created in JavaScript, the JavaScript engine automatically attaches a `prototype` property. Changes to this property are shared among all instances of a particular object type. It is a popular way of adding new properties to existing object constructor functions.
*  ES6 brought classes to JavaScript, which are nothing but a new way of writing constructor functions by utilizing the prototype functionality.

If you want to learn more about objects, here is an in-depth [MDN guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects) that explains how to use objects, properties, and methods.
