ES-6 classes

Code for this and several other ES-6 features can be found in my github


ES-6 has introduced a “class” keyword and “extends” keyword which are similar looking to classes in Java. In reality these are nothing but a syntactic sugar over prototypical inheritance in ES-5.
In ES-5 classes were depicted as follows:

var PersonEs5 = function(firstName, lastName){    
    this.firstName = firstName;    
    this.lastName =lastName;
}
var p1 = new PersonEs5('first','last');
With ES-6 the same class can be written as follows:

class Person{    
constructor(firstName,lastName){        
this.firstName = firstName;        
this.lastName = lastName;    
}
}
Classes are nothing but functions under the cover. If the ES-6 code is compiled down to ES-5, the compiled version will be as follows:

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Person = function Person(firstName, lastName) {
  _classCallCheck(this, Person);

  this.firstName = firstName;
  this.lastName = lastName;
};
So in reality, it is only a function which is syntactically sugared into a class in ES-6. One interesting thing to notice in the compiled version is “_classCallCheck” method.
ES-5 version of Person “PersonEs5”, is just a function. It can be called either by calling the constructor

var p1 = new PersonEs5('first','last');
or directly like invoking any other function

PersonEs5('first','last');
Though both these operations will not produce the same result and the second way of calling it, might be difficult to achieve anything meaningful, it is still technically possible to call it this way.
In ES-6, the “_classCallCheck” method was added to prevent the second way of calling the class, because in reality classes are nothing but functions and it should be technically possible to call classes in the second way (without new keyword).
Some Syntax:
Let us consider the following class and try and break it down syntatically:

const computedMethod = 'concat'
class Person{    
constructor(firstName,lastName){        
this.firstName = firstName;        
this.lastName = lastName;    
}    
fullName() {        
return this.firstName.concat(this.lastName);    
}
get Name(){
    return this.firstName+this.lastName;
}
set Name(n){
    this.name=n;
}
static get StaticName2(){
    return 'StaticName2';
}
[computedMethod](){
    return this.firstName+this.lastName+' from computed';
}
static staticMethod(){
    return 'Static Method';
}
}
Person.StaticName1 = 'StaticName1';
var p1 = new Person('first','last');
console.log(p1.name);
p1.name = 'test';
console.log(p1.name);
console.log(Person.StaticName1);
console.log(Person.StaticName2);
console.log(p1[computedMethod]());
console.log(Person.staticMethod());
  • Instance Variable: Instance variables can be declared within the constructor or they can 
    be declared with in the getters or setters or any methods.
    example: firstName and lastName
  • Instance Methods: Instance methods need not be prefixed with function keyword or they
    dont have to be prefixed with “this.”. It is added implicitly by ES6.
    example: fullName
  • Static variables: There is no support for static variables in ES6. How ever there are a 
    couple of work arounds
  • Add like ES5 after class declaration. Ex: StaticName1
  • Add a static getter. Ex: StaticName2
  • Static Methods: Static methods can be added by prefixing the static keyword.
    Ex:staticMethod
  • Computed Methods: Computed methods are nothing but methods whose names are not decided during compile time but are decided only during execution time. These are represented like accessing/adding computed variable names to an object in javascript. The literal names are represented within square brackets. Example: computedMethod
In reality, everything else is similar to ES-5 prototypical objects. As mentioned earlier, “class” is just a syntactic sugar.
Gotchas:
  • Classes are non-hoisted unlike functions. Hence unlike functions they cannot be used before declaration.
    
    fn1();
    const fn1= ()=>{console.log('random');}
    
While the above is perfectly valid in function, in the case of classes you will get an error saying “class” is not defined.

let c1= new Class1('test');
const Class1= class {
constructor(name){
this.name = name;
}
}
The above code will throw an error since, the class is instantiated before creation.
  • However, the following will not result in an error:
    
    const fn = ()=>{let c1= new Class1('test');}
    const Class1= class {
    constructor(name){
    this.name = name;
    }
    }
    fn();
    
In this case,though the function is created and the class in instantiated before class creation, the function is executed only after class creation and hence, this will not throw an error.
  • If the function is called before class creation, that will result in an error.:
    
    const fn = ()=>{let c1= new Class1('test');}
    fn();
    const Class1= class {
    constructor(name){
    this.name = name;
    }
    }
    

Comments

Popular posts from this blog

Docker Commands

Dockerfile