Hello and welcome to our new session on JavaScript classes! Classes in JavaScript resemble blueprints used for creating similar objects. If you're a video game player who regularly creates characters, each character possesses different properties but shares common attributes. In this context, classes act as your templates. In this lesson, we'll explore the structure of classes, their main methods, and examine getters and setters.
JavaScript classes are essentially the molds for creating objects. They encompass data and behaviors that belong to the object. The structure for defining a class includes the class
keyword followed by the name of the class.
JavaScript1class Dog { 2 constructor(name) { 3 this.name = name; 4 } 5}
In this Dog
class, we have a property called name
, which is set in a special function named the constructor()
. The constructor
is automatically called when we create a new instance of the class.
In object-oriented programming, an "instance" is an object created from a specific class. We can create a new instance in JavaScript using the new
keyword:
JavaScript1let myDog = new Dog('Spot');
In this line of code, new Dog('Spot')
creates a new instance of the Dog
class, with the name
property set to 'Spot'. The new
keyword is essentially telling JavaScript to create a new object, and then invoke the constructor function on that object.
Within the class, we also often see and use the this
keyword. The this
keyword in JavaScript is a little complex as it behaves differently depending on the context it is used in. In a class, this
refers to the instance of the class. In other words, it refers to the object that is created from the class.
For example, when we use this.name = name;
in our constructor, this
is referring to the instance of the Dog being created, and this.name
is setting the name
property of that specific Dog instance.
The instance of the class, such as myDog
in this case, is a full-fledged object with properties and behaviors as defined by the class structure. We can easily access these properties, like so:
JavaScript1console.log(myDog.name); // "Spot"
When you see this code, the dot notation ".name" accesses the name
property of myDog
and returns its value. It's actually accessing this.name
for the myDog
object.
So, whenever you see this
in a method inside a class, think of this
as the object which the method is acting on.
The class structure is defined using the class
keyword followed by the class's name. Inside, we define a constructor
method that initializes object properties and additional methods that define class actions or behaviors. If we want our dogs to bark, we can add a bark
method:
JavaScript1class Dog { 2 constructor(name) { 3 this.name = name; 4 } 5 6 bark() { 7 // The keyword 'this' represents the instance of the class 8 return `${this.name} says woof!`; 9 } 10} 11 12let myDog = new Dog('Spot'); 13// 'bark' method being used on 'myDog' instance of Dog class 14console.log(myDog.bark()); // "Spot says woof!"
With this addition, our Dog
class now includes a bark
method, meaning Spot
can bark.
Getters and setters are special methods that allow us to manipulate an object's properties.
Getters in a class are methods that get the value of a specific property. To define a getter, we use the get
keyword in front of a function.
Let's modify the Dog
class to include a getter for the name
property:
JavaScript1class Dog { 2 constructor(name) { 3 this._name = name; // the underscore (_) is a common convention for private properties which will be discussed later 4 } 5 6 // Define a getter for the 'name' property 7 get name() { 8 return this._name; 9 } 10}
Here, the get
keyword before the name
function makes it a getter, which means it will be automatically invoked when we access the name
property.
Now, we can create a Dog
instance and use our getter to access its name
property:
JavaScript1let myDog = new Dog('Spot'); 2console.log(myDog.name); // "Spot"
Here, when we use myDog.name
, instead of directly returning the value of myDog._name
, it invokes the getter method that returns the value of this._name
of the myDog
object. This allows us to abstract away the underlying data and present a simple interface for getting the name
attribute of a Dog
, making our code more flexible and easier to maintain.
Following the getters, we now have setter methods. They allow us to run some code every time a specific property is attempted to be changed, or 'set'.
We can create a setter for the name
property in the Dog
class. We want to make sure that a dog's name is not left blank, so we'll add a check in our setter:
JavaScript1class Dog { 2 constructor(name) { 3 this._name = name; 4 } 5 6 get name() { 7 return this._name; 8 } 9 10 // Define a setter for the 'name' property 11 set name(value) { 12 // Only update _name if value is not empty 13 if (value.length > 0) { 14 this._name = value; 15 } else { 16 console.log("Error: Name cannot be empty."); 17 } 18 } 19}
Here, the set
keyword before our name
method marks it as a setter. It is used to update the value of a property. In this case, the _name
property.
Now, if we create a Dog
instance and use our setter to change its name
property, we can ensure that a meaningful value is set:
JavaScript1let myDog = new Dog('Spot'); 2console.log(myDog.name); // "Spot" 3myDog.name = ''; // Error: Name cannot be empty. 4console.log(myDog.name); // "Spot" 5 6myDog.name = 'Buddy'; 7console.log(myDog.name); // "Buddy"
Here, when we tried to set the name
property to an empty string, it triggered the setter method. As our setter method contains a condition checking that the name cannot be empty, an error message was displayed to the console and the name
property remained unchanged.
Setters are very useful to protect your object's properties from being incorrectly set or to automatically change other properties when one is set. For instance, here it ensures that we don't accidentally leave a dog nameless.
That concludes our session! We explored JavaScript classes, studied their structure and methods, and delved into getters and setters. Although it may seem like quite a bit of information, mastering these fundamentals is key to becoming a well-rounded JavaScript programmer. Devote some time to practicing what you've learned; once you do, you'll find these concepts seamlessly woven into JavaScript programming. These concepts also play a significant part in React, which we'll learn about later. Happy practicing!