So far, we learned that in JavaScript, we can create an object via a pair of braces `{}` which is known as object literal as well as constructor functions together with the `new` keyword.
The third way of creating an object in the JavaScript is via the classes.
In this section, we will give you an overview of the class and how it works, as well as showing you how to create an object from that class. Then, in the next couple of sections, we will get into greater details of each of the members you’ll see in this section.
What is Classes in JavaScript?
Classes are basically templates that we define properties and methods in them. After that, via the `new` operator and the name of the target class, we can create objects. These objects will have the properties and methods we defined in that class.
A class has a name and a body. The body of a class is the place where we define the properties and methods for the objects that will be created from that class.
For example, if you want to have an object with properties like `firstName` and `lastName`, first you need to declare those properties in the body of a class and then use this class to create objects that will have the mentioned properties.
How to Declare Classes in JavaScript? (JavaScript Class Syntax)
Alright, in order to create a class, we first start with the keyword `class` and then the name of that class (you define this name) and then a pair of braces that declare the body of that class.
Here’s the structure:
class className{ //body… }
We define a class with either declarations or expressions.
The structure you saw above is considered a class declaration because this class is not assigned to a variable.
When we assign a class to a variable, it then becomes class expression.
Example:
let className = class className{ //Body… }
Note: when we have a class expression, the name after the keyword `class` becomes optional. So the expression above can be refactored like this:
let className = class{/*body*/}
JavaScript Class Constructor
Now moving on to the body of a class:
If we want the future object of a class to have a specific number of properties, we can declare those properties in a method named `constructor` in the body of the class.
Example:
class Person{ constructor(firstName, lastName){ this.firstName = firstName; this.lastName = lastName } }
Inside the body of the constructor method, we define the properties that we want the objects of this class to possess. Any property that we define in the body of the constructor will be unique for each future object. For example, here we have two properties named `firstName` and the `lastName`. So if we create two objects from the `Person` class, each will have its own `firstName` and `lastName` values and changing one value in one object will not affect the other one.
Notes:
- We need to prepend the `this` keyword to the properties’ names in this method. Read the `this` section if you’re not familiar with the keyword.
- These properties can have a method as their values as well.
You should know that the `constructor` method is not a type of method that can be accessed by the name of the object just like the way you saw so far. The `constructor` method is only accessible when we’re creating an object from the class. This means only via the `new` and `super` keywords!
JavaScript Class Function and Properties
As mentioned in the `prototype` section, every function has an object that can be accessed via the `prototype` property of that function. The members (properties and methods) that we define in this prototype-object are shared between all the objects that are created from that function.
Likewise, the members that we define in the body of a class (excluding the constructor) are shared between the objects that will be created from that class. Basically, you can consider the body of a class as the prototype-object and the members in this body as the member of the prototype-object. It is important to know this fact because a created object of a class can, for example, add a new member to the class or change the functionality of a method and other future objects of this class will see the change as well!
Note: if you have a Java or C# background, this might confuse you at first, but just remember this: only those members in the constructor method will be copied for each object. Outside of the `constructor` method, members are shared between objects of that class. (It’s somewhat like the static methods in C# and Java).
Example: creating a class in JavaScript
class Person{ constructor(firstName, lastName){ this.firstName = firstName; this.lastName = lastName } getFirstName(){ return this.firstName; } setFirstName(firstName){ this.firstName = firstName; } }
Notes:
- Between each method, we don’t use the comma `,` to separate them from each other.
- Also, the rules that apply to `this` keyword, works the same in a class method as well.
So here we have two methods that if we call them, it will allow us to get or set the value of the `firstName` property.
Instance of a Class in JavaScript
The object that we create from a class is known as the instance of that class.
To create an object from a class, we can use the `new` keyword. Basically, there’s no difference between a constructor function and a class when it comes to creating an object via the `new` keyword.
Example: creating instance of a class in JavaScript via the new keyword
class Person{ constructor(firstName, lastName){ this.firstName = firstName; this.lastName = lastName } getFirstName(){ return this.firstName; } setFirstName(firstName){ this.firstName = firstName; } } const prs = new Person("John","Doe"); console.log(prs.firstName); console.log(prs.lastName);
Output:
John Doe
Take a look at this statement:
const prs = new Person("John","Doe");
When we called the `Person(“John”, “Doe”)`, in the background, the `constructor` method of the `Person` class is invoked. The values `John` and `Doe` are assigned to the parameters `firstName` and `lastName` respectively, and the execution engine will invoke the body of this method and run its instructions.
At the end, when the engine reaches to the end of the `constructor` method, it will return the newly created object and assign that to the `prs` identifier (the memory address of the newly created object of course).
Note: There’s no difference between an object that is created from a class and other types of objects that we create via object-literal or constructor functions.
JavaScript Classes and Temporal Dead Zone
You should know that unlike constructor functions, classes will not hoist! Just like `let` and `const`, classes have TDZ (Temporal Dead Zone) as well. So until a class is not fully initialized, we can’t use the name of that class to create objects.
Example: Classes in JavaScript and TDZ
let pr = new Person("John", "Doe"); class Person{ constructor (firstName, lastName){ this.lastName = firstName; this.firstName = lastName; } static getName(){ return this.firstName; } setName(name){ this.firstName = name; } getLastName(){ return this.lastName; } setLastName(lastName){ this.lastName = lastName; } }
Output:
Uncaught ReferenceError: Cannot access 'Person' before initialization
Alright, that’s it for this section! In the next couple of sections, we will get into more details about the `constructor` method, other methods in a class, static methods, super keyword, inheritance and a few more.