BEFORE ES6
Specifications before ES6 had no classes, but JavaScript offered a somewhat similar approach, using a constructor to whose prototype we could assign our own methods:
//first we create a constructor
function Car(name) {
this.name=name;
}
//we add a method makeItDope to the Car prototype
Car.prototype.makeItDope = function() {
console.log(this.name + " is dope");
}
//we create a new car
var newCar = new Car("Audi");
newCar.makeItDope(); // 'Audi is dope'
Before ES6, many libraries helped us recreate the behavior of classes using the method above. You could say that this was probably the beginning of the class concept that was eventually implemented in ES6.
HOW TO CREATE A CLASS
You can often find the term that classes in JS are a sugar syntax for what was in before ES6. There is a point in this (but not entirely, more on that later). Class, like a function, have two forms - a declaration and an expression.
//DECLARATION
//We start with the `class`
class Car {
//we create a constuctor method
constructor(name) {
this.name=name;
}
//You don't need to add the `function` word
// no commas are required between the class elements
makeItDope() {
console.log(this.name + " is dope")
}
}
let newCar = new Car('Audi');
newCar.makeItDope() //'Audi is dope'
//EXPRESSION
let Car = class {
constructor(name) {
this.name=name;
}
makeItDope() {
console.log(this.name + " is dope")
}
}
let newCar = new Car('Audi');
newCar.makeItDope() //'Audi is dope'
You can also use named class expression:
//EXPRESSION
let Car = class CarClas {
constructor(name) {
this.name=name;
}
makeItDope() {
console.log(this.name + " is dope")
}
}
let newCar = new Car('Audi');
newCar.makeItDope() //'Audi is dope'
At first glance, it looks like the classes are actually just a different syntax to what was going on in ES5. However, apart from this aesthetic change, there are still quite a few differences that you should keep in mind.
Not such a sugar syntax
- Classes, unlike functions, are not hoisted
//That's ok!
var newCar = new Car("Audi")
function Car(name) {
this.name = name;
}
//ReferenceError: Cannot access 'Car' before initialization
let newCar = new Car("Audi")
class Car {
constructor(name) {
this.name=name;
}
}
- Inside class, there is no way to override strict mode
- None of the methods in the class are enumerable, so you can't access them with
for..in
orObject.keys()
- The methods inside the class do not have an
construct
method, so using them with thenew
operator will throw an error - You cannot call a class constructor without using the
new
operator
STATIC METHODS
Static methods are another thing that is not new and was already available in ES5:
function Car(name) {
this.name = name;
}
Car.theBestCar = function() {
return "FIAT MULTIPLA!"
}
Car.prototype.makeItDope = function() {
return this.name + ' is Dope!'
}
var newCar = new Car('Audi')
console.log(Car.theBestCar()) // FIAT MULTIPLA!
console.log(newCar.theBestCar()) //TypeError: newCar.theBestCar is not a function
console.log(newCar.makeItDope()) //Audi is Dope!
To create a static method in a class, you must use the word static:
class Car {
constructor(name) {
this.name = name;
}
static theBestCar() {
return "FIAT MULTIPLA!"
}
makeItDope() {
return this.name + ' is Dope!'
}
}
let newCar = new Car('Audi')
console.log(Car.theBestCar()) // FIAT MULTIPLA!
console.log(newCar.theBestCar()) //TypeError: newCar.theBestCar is not a function
console.log(newCar.makeItDope()) //Audi is Dope!
Static items are not available from the instance level. They can only be accessed from the class level.
INHERITANCE
Another example of how class syntax is superior to ES5 is the way we code inheritance. The example below shows what it looked like in the ES5 era (IMO the easiest example):
function Rectangle(length, width) {
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function() {
return this.length * this.width;
}
function Square(length) {
Rectangle.call(this, length, length)
}
Square.prototype = Object.create(Rectangle.prototype, {
constructor: {
value: Square,
enumarable: true,
writable: true,
configurable: true
}
});
var mySquare = new Square(5)
console.log(mySquare.getArea()) //25
As you can see, it is not that simple, and in my opinion it is not even easy to understand at first glance.
If we wanted to use inheritance in the case of class
, all we need to do is use the word extends
, which indicates the function to inherit from, and the super
method that allows us to access the base class
constructor:
class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width
}
getArea() {
return this.length * this.width
}
}
class Square extends Rectangle {
constructor(length) {
super(length, length)
}
}
let mySquare = new Square(5)
console.log(mySquare.getArea()) //25
Here are some things you should keep in mind about inheritance:
- If a constructor is given in the derived class, you must use
super()
. - The
super()
method can only be used in a derived class constructor. - The
super()
method must be called before accessing the this binding. - Methods in derived classes always override methods with the same name in the base class.
-
static
methods are also inheritable.
End of Part One.
πThanks for reading!π
Top comments (0)