How to use JavaScript Classes
By Flavio Copes
Learn how to use JavaScript classes introduced in ES6, from defining a constructor and methods to creating objects with new and inheritance using extends.
In 2015 the ECMAScript 6 (ES6) standard introduced classes.
JavaScript has a quite uncommon way to implement inheritance: prototypical inheritance. Prototypal inheritance, while in my opinion great, is unlike most other popular programming language’s implementation of inheritance, which is class-based.
People coming from Java or Python or other languages had a hard time understanding the intricacies of prototypal inheritance, so the ECMAScript committee decided to sprinkle syntactic sugar on top of prototypical inheritance so that it resembles how class-based inheritance works in other popular implementations.
This is important: JavaScript under the hood is still the same, and you can access an object prototype in the usual way.
A class definition
This is how a class looks.
class Person {
constructor(name) {
this.name = name
}
hello() {
return 'Hello, I am ' + this.name + '.'
}
}
A class has an identifier, which we can use to create new objects using new ClassIdentifier().
When the object is initialized, the constructor method is called, with any parameters passed.
A class also has as many methods as it needs. In this case hello is a method and can be called on all objects derived from this class:
const flavio = new Person('Flavio')
flavio.hello()
Class inheritance
A class can extend another class, and objects initialized using that class inherit all the methods of both classes.
If the inherited class has a method with the same name as one of the classes higher in the hierarchy, the closest method takes precedence:
class Programmer extends Person {
hello() {
return super.hello() + ' I am a programmer.'
}
}
const flavio = new Programmer('Flavio')
flavio.hello()
(the above program prints “Hello, I am Flavio. I am a programmer.”)
Inside a class, you can reference the parent class calling super().
Class fields
You can declare public fields on the class body. They land on each instance, and you do not have to assign them only inside the constructor:
class Person {
age = 0
constructor(name) {
this.name = name
}
}
const flavio = new Person('Flavio')
flavio.age //0
There is still no protected keyword in JavaScript. Privacy is handled with #, which we cover next.
Static methods
Normally methods are defined on the instance, not on the class.
Static methods are executed on the class instead:
class Person {
static genericHello() {
return 'Hello'
}
}
Person.genericHello() //Hello
You can also use a static {} block for one-time setup on the class itself, when you need more than a simple static field.
Private fields and methods
Private fields and methods use a # prefix. They are real language features now, not a naming convention. Code outside the class cannot read or call them:
class Person {
#name
constructor(name) {
this.#name = name
}
#greet() {
return 'Hello, I am ' + this.#name + '.'
}
hello() {
return this.#greet()
}
}
const flavio = new Person('Flavio')
flavio.hello() //Hello, I am Flavio.
// flavio.#name //SyntaxError
You can also mark static members private with #:
class Counter {
static #count = 0
static next() {
return ++Counter.#count
}
}
A leading underscore like _name is still just a soft convention. It does not hide anything. There is no protected access level.
Getters and setters
You can add methods prefixed with get or set to create a getter and setter, which are two different pieces of code that are executed based on what you are doing: accessing the variable, or modifying its value.
class Person {
constructor(name) {
this._name = name
}
set name(value) {
this._name = value
}
get name() {
return this._name
}
}
If you only have a getter, the property cannot be set, and any attempt at doing so (outside of the constructor, which sets the value when you initialize a new object with this class) will be ignored:
class Person {
constructor(name) {
this._name = name
}
get name() {
return this._name
}
}
If you only have a setter, you can change the value but not access it from the outside:
class Person {
constructor(name) {
this._name = name
}
set name(value) {
this._name = value
}
}
Getters and setters are very useful when you want to execute some code upon changing the property value, or if you want to create a “computed” property. You can alter the values you return by using a getter.
You can also run some code, like logging to the console or to a file when a value is changed.
Want me to talk about your product? You can sponsor this site.
Related posts about js: