JavaScript classes are simply syntactic sugar over existing JavaScript prototype chain. But classes give you a cleaner way to organise your code, and make it slightly easier for the beginner or people who are familiar with class oriented languages to read JS and understand.
Let's have a look at how ES5 way of doing the same thing:
function Vehicle(doors, wheels) {
this.doors = doors;
this.wheels = wheels;
}
Vehicle.prototype.startEngine = function() {
this.engineState = 'started';
console.log('Engine started ..');
};
Vehicle.prototype.stopEngine = function() {
this.engineState = 'stopped';
console.log('Engine stopped ..');
};
Vehicle.prototype.drive = function() {
if(this.engineState == 'started') {
console.log('driving ..');
} else {
console.log('start the engine first!');
}
}
}
var car = new Vehicle(2, 4);
car.startEngine();
Now let's look at the ES6 implementation:
class Vehicle {
constructor(doors, wheels) {
this.doors = doors;
this.wheels = wheels;
}
startEngine() {
this.engineState = 'started';
console.log('Engine started ..');
}
stopEngine() {
this.engineState = 'stopped';
console.log('Engine stopped ..');
}
drive() {
if(this.engineState == 'started') {
console.log('driving ..');
} else {
console.log('start the engine first!');
}
}
}
var car = new Vehicle(2, 4);
car.startEngine();
You can probably notice the differences between the two. We instantiate our classes the same way we would if we were building our code from an ES5 perspective, but there are a few subtle differences.
ES6 classes provide these benefits:
- They are backwards compatible with much of the current code.
- Classes make it easier for beginners to get started.
- Subclassing is supported within the language.
- Built-in constructors are subclassable.
- No library for inheritance is needed, anymore; code will become more portable between frameworks.
- They provide a foundation for advanced features in the future (mixins and more).
- They help tools that statically analyze code (IDEs, type checkers, style checkers, etc.).
Readability
You don’t realise how messy Javascript is until you work on a large-scale project comprised of more than two developers, ES6 classes come with all of the benefits of pre-existing prototypical inheritance, but require less typing and they make your code easier to understand and resemble closely an object-oriented programming language like Java and its approach to classes.
There are plans to introduce object-oriented syntax like; static, public, private in ES7, but we’ll wait and see if they make the cut.
Better IDE Support
When coupled with a strong IDE and tooling, ES6 classes can be powerful in that they can be analysed by the IDE and we are given more options for tracing methods (especially when extending parent classes). Webstorm supports classes quite well when used with ES6.
Base Classes
The class definition of ES6 looks like this:
class Base {
constructor(x, y) {
this.x = a;
thisy = y;
}
sum() {
return this.x + this.y;
}
}
You can only invoke a class via new
, not via a function call.
typeof Base; // 'function'
Base(); // TypeError: Classes can’t be function-called
Class Expressions
Just like functions, there are two ways to define a class: declarations
and class expression
.
const Base = class Self {
getClassName() {
return Self.name;
}
}
let instance = new Base();
instance.getClassName(); // Self
Self.name; // ReferenceError: Self is not defined
Constructor
The pseudo-method constructor
is special, as it defines the function that represents the class:
Foo === Foo.prototype.constructor; // true
typeof Foo; // 'function'
This is sometimes called class constructor
. It has features that normal constructor functions don’t have, mainly the ability to constructor call its superconstructor via super()
.
Static Methods
Static properties (or class properties) are properties of the class itself. If you prefix a method definition with static, you create a class method:
typeof Foo.staticMethod; // 'function'
Foo.staticMethod(); //'classy'
Prototype Methods
The prototype properties of Foo are the properties of Foo.prototype. They are usually methods and inherited by instances of Foo.
typeof Foo.prototype.prototypeMethod //'function'
foo.prototypeMethod() // 'prototypical'
Getters and Setters
The syntax for getters and setters is just like in ES5 object literals:
class Bar {
get foo() {
return 'foo';
}
set foo(value) {
value;
}
}
var bar = new Bar();
Subclassing
The extends
clause lets you create a subclass of an existing constructor (which may or may not have been defined via a class):
class Base {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
return this.x + this.y;
}
}
class Child extends Base {
constructor(x, y, z) {
super(x, y);
this.z = z;
}
sum() {
return super.x + super.y + this.z;
}
}
var child = new Child(15, 8 , 3);
child.sum();