Two Problems of a JavaScript Class

Dhananjay Kumar / Friday, December 21, 2018

Starting ECMA 6, JavaScript has class keyword to create a class. I have written in detail about class here. There is no second question that class simplifies the way object is created, inheritance is implemented etc. JavaScript class has,

  • Constructors
  • Methods
  • Extends etc.

Above features of a class helps to easily write Object Oriented JavaScript. As a developer, you do not need to know complexities of prototype chains, relationship between function constructor and its prototype object, and value of object’s __proto__ properties etc. to write effective Object Oriented JavaScript.  So, class keyword  is good addition to JavaScript language, however it is not gospel perfect. It has some problems, which may restrict you to write full-fledged Object Oriented JavaScript. In this post, I am going to share two such problems. Read along,

No Static Member Properties in Class

A static member property is shared by all object instance of the class. JavaScript class does not allow creating it inside the class.

You cannot declare properties directly in the class. You can only have it through class’s constructors, and properties created inside constructor is local to the object instances and not shared by all of them.

class Car {
 
	var a = 9; // unexpected indentifier error 
}

Above code will throw error “unexpected identifier”.  There is a work around to create static property using the class prototype.

class Speaker {
    constructor(name) {
            Speaker.prototype.count++;
            this.name = name;
        }
    }
Speaker.prototype.count = 0; 

Now on the instances of Speaker class, you can access static property count.

var a = new Speaker('dj');
var b = new Speaker('Jason');
 
console.log(a.count); // 2
console.log(b.count); // 2
console.log(a.count === b.count) // true 

Therefore, you are able to create a static property, but not without help of understanding of prototype.  In my opinion class should have a way to create static property directly inside the class like a method or constructor.

Object Instances Does Not Copy Definitions From Class

To understand this problem, let us first revise Constructor Invocation Pattern and prototype chain. You have a function constructor Speaker.

function Speaker(name) {
    this.name = name;
    this.hello = function () {
        console.log('hey ' + this.name);
    }
}

Using new operator, you can create object instances,

var a = new Speaker('dj');
a.hello(); // hey dj 
var b = new Speaker('Jason');
b.hello(); // hey Jason

In this approach, a and b object instances both have their own copy of hello method.  Now if you add a hello method to Speaker.prototype, still a and b object instances will access their own copy of hello method. Consider below code:

Speaker.prototype.hello = function () {
    console.log('Hello Speaker ' + this.name);
}
 
a.hello(); // hey dj 
b.hello(); // hey Jason 
a.__proto__.hello.call(a); // Hello Speaker DJ 

You are getting expected output while calling hello method and to call hello method of Speaker prototype use __proto__.

Now let us implement above scenario using class.

class Speaker {
 
    constructor(name) {
        this.name = name;
    }
    hello() {
        console.log('hey ' + this.name);
    }
}

We have created Speaker class with a constructor and an instance method hello. Let us create object instances of Speaker class,

var a = new Speaker('dj');
a.hello(); // hey dj 
var b = new Speaker('Jason');
b.hello(); // hey Jason

So far, everything is as expected. Now go ahead and add same function hello to Speaker prototype.

Speaker.prototype.hello = function () {
    console.log('hello speaker  ' + this.name);
}

After adding function hello to speaker prototype, call hello function with object instances of Speaker.

a.hello(); // hello speaker dj 
b.hello(); // hello speaker jason 

You will find surprised output that object instances a and b are now calling hello function of Speaker prototype instead of their own hello function.

This is happening because JavaScript class is not like real class of object-oriented language. It does not create copy of class declaration in objects. It is still using the live delegation model based on [[Prototype]]

 Besides, above two problems in class, there are others too. One is related to super keyword which we will discuss in further article. I would recommend you to learn more about class, function constructor, and prototypes before deciding which one you should use.

Infragistics Ignite UI for JavaScript