13. Classes

Here we introduce the classes of ECMAScript 6. First, we show that functions can already be used as classes.
13.1. script [class-00]
The following script demonstrates an unusual use of functions. Here, they are used as objects.
'use strict';
// a function can be used as an object
// an empty shell
function f() {
}
// to which external properties are attributed
f.prop1 = "val1";
f.show = function () {
console.log(this.prop1);
}
// use of f
f.show();
// a function g operating as a class
function g() {
this.prop2 = "val2";
this.show = function () {
console.log(this.prop2);
}
}
// instantiate the function with [new]
new g().show();
Comments
- lines 5–7: the body of function f does not define any properties;
- lines 9–12: properties are assigned to the function f from outside;
- line 14: use of the function (object) f. Note that we do not write [f()] but simply [f]. This is the notation for an object;
- lines 17–22: we define a function [g] as if it were a class with properties and methods;
- line 24: the function [g] is instantiated by [new g()];
Execution results
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-00.js"
val1
val2
ES6 introduced the concept of classes, which now allows us to avoid using functions to create classes.
13.2. script [class-01]
The script [class-01] introduces a class [Personne]:
// class
class Personne {
// manufacturer
constructor(nom, prénom, âge) {
this.nom = nom;
this.prénom = prénom;
this.âge = âge;
}
// getters and setters
get nom() {
return this._nom;
}
set nom(value) {
this._nom = value;
}
get prénom() {
return this._prénom;
}
set prénom(value) {
this._prénom = value;
}
get âge() {
return this._âge;
}
set âge(value) {
this._âge = value;
}
// toString to JSON
toString() {
return JSON.stringify(this);
}
}
// class call
function main() {
const personne = new Personne("Poirot", "Hercule", 66);
console.log("personne=", personne.toString(), typeof (personne), personne instanceof (Personne));
}
// hand call
main();
Comments
- line 2: the keyword [class] denotes a class;
- lines 5–9: the keyword [constructor] denotes the class constructor. There can be at most one. It is used to construct and initialize an instance of the class. Note that there is no declaration of the properties [nom, prénom, âge];
- lines 11–36: class properties. Here we see elements already covered in the section on objects 4, page 44. Only the syntax differs;
- line 41: creation of an object of type [Personne]. From now on, the object [personne] is used as a literal object. [typeof (personne)] evaluates to “object” and the expression [personne instanceof (Personne)] is true. It is therefore possible to determine the exact type of a class instance;
Execution results
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-01.js"
personne= {"_nom":"Poirot","_prénom":"Hercule","_âge":66} object true
13.3. script [class-02]
This script demonstrates the ability to inherit from a class using the keyword [extends].
First, we isolate the [Personne] class in a [Personne.js] module:
// class
class Personne {
// manufacturer
constructor(nom, prénom, âge) {
this.nom = nom;
this.prénom = prénom;
this.âge = âge;
}
// getters and setters
get nom() {
return this._nom;
}
set nom(value) {
this._nom = value;
}
get prénom() {
return this._prénom;
}
set prénom(value) {
this._prénom = value;
}
get âge() {
return this._âge;
}
set âge(value) {
this._âge = value;
}
// toString to JSON
toString() {
return JSON.stringify(this);
}
}
// export class
export default Personne;
- line 39: we export the [Personne] class so that scripts can import it;
The script [class-02] creates a class [Enseignant] derived from the class [Personne]:
// imports
import Personne from './Person';
// class
class Enseignant extends Personne {
// manufacturer
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// getters and setters
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
}
// class call
function main() {
const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}
// hand call
main();
Comments
- line 2: we import the [Personne] class from the [Personne.js] module, which is located in the same folder as [class-02];
- line 5: the [Enseignant] class extends (inherits from) the [Personne] class using the [extends] keyword: it adds a property [_discipline] with the corresponding getter and setter methods;
- lines 8–11: the constructor of the [Enseignant] class receives four values to initialize the class’s four properties;
- line 9: the keyword [super] calls the constructor of the parent class [Personne], which will then initialize the properties [_nom, _prénom, _âge];
- line 10: the property [_discipline], which belongs to the class [Enseignant], is initialized;
- lines 14–19: the getter and setter for the property [_discipline];
- line 25: an object of type [Enseignant] is created;
- line 26: the method [enseignant.toString()] is used. The class [Enseignant] does not have this method. In this case, the method from its parent class is automatically used. This method causes the expression [JSON.stringify(this)]—where [this] will be an object of type [Enseignant] rather than an object of type [Personne]. This is what is known in object-oriented programming as class polymorphism. A big word for Javascript, which is not an object-oriented language. Nevertheless, Javascript does what is expected of it here: it correctly displays a teacher;
The results of the execution are as follows:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-02.js"
enseignant= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object true
- line 2: Javascript correctly recognizes that the variable [enseignant] is of type [Enseignant];
13.4. script [class-03]
The script [class-03] demonstrates that a child class can override properties and methods of its parent class. Here, we override the method [toString] of the parent class:
// imports
import Personne from './Person';
// class
class Enseignant extends Personne {
// manufacturer
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// getters and setters
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
// redefinition of toString
toString() {
return "[Enseignant]" + JSON.stringify(this);
}
}
// class call
function main() {
const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}
// hand call
main();
The results of the execution are as follows:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-03.js"
enseignant= [Enseignant]{"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object true
13.5. script [class-04]
The script [class-04] again demonstrates polymorphism in action: where a function expects a formal parameter of type [Personne], a derived type such as [Enseignant] can be passed. In fact, due to derivation, the type [Enseignant] has all the attributes of the type [Personne].
First, we isolate the type [Enseignant] into a module [Enseignant.js]:
// imports
import Personne from './Person';
// class
class Enseignant extends Personne {
// manufacturer
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// getters and setters
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
}
// export class
export default Enseignant;
- line 24: the [Enseignant] class is exported so that other scripts can import it;
The script [class-04] is as follows:
// imports
import Enseignant from 'teacher';
import Personne from './Person';
// function accepting a person as parameter
function show(personne) {
// in all cases
console.log("paramètre=", personne.toString(), typeof (personne));
// instance of Person
if (personne instanceof Personne) {
console.log("personne=", personne.toString());
}
// instance of Teacher
if (personne instanceof Enseignant) {
console.log("enseignant=", personne.toString());
}
}
// show call with a teacher
show(new Enseignant("Poirot", "Hercule", 66, "détective"));
show(new Personne("Marple", "Miss", 70));
- line 6: the function [show] expects a type [Personne] or a derived type;
- line 8: we display the parameter string and its type. We will find [object];
- lines 10–16: we can determine whether it is a type [Personne] or a type [Enseignant]. The code can therefore be adapted to the actual type of the parameter;
The execution results are as follows:
[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-04.js"
paramètre= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object
personne= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"}
enseignant= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"}
paramètre= {"_nom":"Marple","_prénom":"Miss","_âge":70} object
personne= {"_nom":"Marple","_prénom":"Miss","_âge":70}
- lines 4 and 6: Javascript correctly identifies the type of class instances;