A brief review
Let's start with a summary of what we have discussed in the past few lessons.
We know that there is a this
keyword for JavaScript functions. When used in an object, it refers to the current instance of that object.
1let user = {
2 name: "John",
3 hi() {
4 console.log(`Hello, ${this.name}!`);
5 },
6};
7
8user.hi();
1Hello, John!
Unlike the this
keyword in other programming languages, JavaScript allows this
to exist outside of an object, which enables us to build constructor functions like this:
1function User(name) {
2 this.name = name;
3 this.hi = function () {
4 console.log(`Hello, ${this.name}!`);
5 };
6}
7
8let user = new User("John");
9
10console.log(user.name);
11user.hi();
1John
2Hello, John!
Constructor functions are used to programmatically create objects. You can create both properties and methods with a constructor function.
There are two special properties in objects called getters and setters. As the name suggests, they are used to get or set property values.
1let user = {
2 firstName: "John",
3 lastName: "Doe",
4
5 get name() {
6 return `${this.firstName} ${this.lastName}`;
7 },
8
9 set name(name) {
10 [this.firstName, this.lastName] = name.split(" ");
11 },
12};
13
14console.log(user.name);
15
16user.name = "Alice Cooper";
17
18console.log(user.name);
1John Doe
2Alice Cooper
You can create an inheritance system using objects by setting an object to be the prototype of another object, which can be the prototype of another object, and so on.
1let user = {
2 . . .
3};
4
5let admin = {
6 role: "Admin",
7};
8
9Object.setPrototypeOf(admin, user);
10
11let profile = {
12 created: "2022-09-01",
13};
14
15Object.setPrototypeOf(profile, admin);
All of these concepts we have discussed so far in the past few lessons belong to a programming paradigm called object-oriented programming, where you divide the program into reusable pieces in the form of objects.
And because this programming paradigm is so popular, JavaScript offers a more standard syntax called the class notation.
Using the standard class syntax
Instead of a separate constructor function, you can define a class using the class
keyword, and inside that class, create a constructor()
function. Again, it is conventional for classes to be named with uppercase letters.
1class User {
2 constructor(firstName, lastName) {
3 this.firstName = firstName;
4 this.lastName = lastName;
5 }
6}
To call this constructor()
function, use the same keyword new
, and the class name.
1let user = new User("John", "Doe");
2
3console.log(user);
1User { firstName: 'John', lastName: 'Doe' }
To create methods, instead of putting them inside the constructor()
function, they are placed at the same level as the constructor()
.
1class User {
2 constructor(firstName, lastName) {
3 this.firstName = firstName;
4 this.lastName = lastName;
5 }
6
7 printFullName() {
8 console.log(`${this.firstName} ${this.lastName}`);
9 }
10}
11
12let user = new User("John", "Doe");
13
14user.printFullName();
1John Doe
What is a class
So, what exactly is a class? In JavaScript, class is a function. It is not a language-level entity. It is just a syntax sweetener for creating constructor functions. You can verify this using the typeof
operator.
1class User {
2 constructor(firstName, lastName) {
3 this.firstName = firstName;
4 this.lastName = lastName;
5 }
6}
7
8console.log(typeof User);
1function
When you define a class, let's say User
, JavaScript will create a constructor function internally, and the corresponding properties will be created based on the information provided in the constructor()
.
The methods, on the other hand, will be stored in User.prototype
. When you call a method under User
, that method is actually taken from prototype
. This can be verified with the following example.
1class User {
2 constructor(firstName, lastName) {
3 this.firstName = firstName;
4 this.lastName = lastName;
5 }
6
7 example() {
8 console.log("This method in in the prototype.");
9 }
10}
11
12User.prototype.example();
1This method in in the prototype.
Just like a regular function, the classes can be assigned to a variable, passed as an argument, returned as an output, and more.
1let User = class {
2 constructor(firstName, lastName) {
3 this.firstName = firstName;
4 this.lastName = lastName;
5 }
6
7 example() {
8 console.log("This method in in the prototype.");
9 }
10};
11
12let user = new User("John", "Doe");
1function createUserClass() {
2 return class {
3 constructor(firstName, lastName) {
4 this.firstName = firstName;
5 this.lastName = lastName;
6 }
7
8 example() {
9 console.log("This method in in the prototype.");
10 }
11 };
12}
13
14let User = createUserClass();
15
16let user = new User("John", "Doe");
Getters and setters
The getters and setters in the class are created in a similar way.
1let User = class {
2 constructor(name) {
3 // Invoking the setter
4 this.name = name;
5
6 // These fields will be filled by the setter
7 this.firstName;
8 this.lastName;
9 }
10
11 get name() {
12 return `${this.firstName} ${this.lastName}`;
13 }
14
15 set name(name) {
16 [this.firstName, this.lastName] = name.split(" ");
17 }
18};
19
20let user = new User("John Doe");
21
22console.log(user);
1User { firstName: 'John', lastName: 'Doe' }