Object-Oriented Programming
In the previous task, we refactored our todo app using a functional programming approach. We used closures, higher-order functions, and immutable data structures, which are the principles of functional programming. In this section, we will look at an object-oriented way to structure and organize the same code.
In object-oriented programming, we model our application as a collection of objects that interact with each other. Each object has its own state and behavior. We can use classes to define the structure of our objects and create instances of these classes to represent individual objects.
In our case, we can define a Todo class that represents a single todo item. Each todo item will have properties like id, text, completed, and methods to toggle the completion status. We can also define a TodoList class that represents a collection of todo items. This class will have methods to add, remove, and filter todo items.
Let’s start by defining the Todo class. Create a new file named todo.js in the src directory and define the Todo class as follows:
Defining the Todo Class
class Todo {
constructor(id, text, completed = false) {
this.id = id;
this.text = text;
this.completed = completed;
}
toggle() {
this.completed = !this.completed;
}
}
This syntax should look familiar if you have experience with other object-oriented programming languages like Java or C++.
Notice that we use the class keyword to define a class in JavaScript. The constructor method is a special method that is called when a new instance of the class is created. We can pass arguments to the constructor to initialize the object’s properties.
The properties id, text, and completed are defined on the Todo class using the this keyword. We could have declared them inside the body of the class, but it is more idiomatic to define them in the constructor method. The completed property has a default value of false if no value is provided when creating a new instance of the Todo class.
The toggle method toggles the completed property by negating its current value. Methods are declared using the method declaration syntax, which we covered in the chapter on JavaScript Functions. Inside a class declaration, unlike in an object literal, method definitions are not separated by a comma.
Instantiating a Todo Object
Now that we have defined the Todo class, let’s create a new instance of the Todo class and test the toggle method. Add the following code to the todo.js file right below the Todo class definition:
const todo = new Todo(1, "Buy milk");
console.log(todo);
todo.toggle();
console.log(todo);
Run the todo.js file using Node.js to see the output. You should see the following output in the console:
Todo { id: 1, text: 'Buy milk', completed: false }
Todo { id: 1, text: 'Buy milk', completed: true }
We use the new keyword to create a new instance of the Todo class. We pass the id and text of the todo item as arguments to the constructor. Notice we do not explicitly call the constructor method; it is called automatically when we create a new instance of the class.
We then call the toggle method on the todo object using the familiar dot notation. We log the todo object to the console before and after calling the toggle method to see the updated completion status.
Accessing and Modifying Properties
In JavaScript, class properties are public by default, which means they can be accessed and modified from outside the class. To see how this works, add the following code to the todo.js file:
console.log(todo.id);
console.log(todo.text);
console.log(todo.completed);
todo.id = 2;
console.log(todo);
Run the todo.js file using Node.js to see the output. You should see the following output in the console:
1
Buy milk
true
Todo { id: 2, text: 'Buy milk', completed: true }
Reading and changing an object’s properties directly is flexible, but it also exposes the internal state of the object. If properties are changed without validation or error checking, that can lead to unexpected behavior. In the next step, we will look at a technique to hide the internal state of an object from code outside the class.
Checkpoint: Commit your progress.
git add .
git commit -m "todos-15: Create Todo class with basic methods"
git push