Classless Javascript (Composition over Inheritance)

Nikhil Yeole
Frontend Weekly
Published in
5 min readJun 1, 2016

A lot has been said about why we don’t need Class syntax in javascript. And that’s quite true, because javascript works on prototypal inheritance unlike other classical inheritance languages, such as ruby, python, php, java, c#. I think if somebody wants to use OOP/inheritance in JS then it should be in accordance with prototypal nature of JS.

There are numerous examples available all over the internet to show how we can exactly simulate classical “Classes” using prototypes. All features like private variables, class/static variables etc. can be emulated easily. However people have long complained that prototypal inheritance(and in general whole JS) is so fexible that there are multiple ways/styles of writing classes and that creates confusion, especially to javascript new comers. I think this is also true!

So, ES6 presented us uniform way of writing classes with ‘class’ keyword which looks like normal ‘class’ of other classical languages but actually is just a sugar syntax over prototypal behaviour. So many say that having ‘class’ keyword in javascript adds consistency in writing (more so in reading..remember we read a lot more code than we actually write) classes in javascript. Again true!

Okay, so this article is not about “Should we use ‘class’ keyword for classes or write classes according to prototypes?”. My point is that we do not need classes and inheritance! So no to “class” keyword and even no to “prototypal inheritance”. And remember that our ultimate aim is “code reuse”, either by inheritance or by other mechanisms. So actually by not using inheritance (prototypal in JS’s case) and ‘class’ we would make already small language even smaller, and for good!

Javascript has superb support for first class functions and closures. So we can actually use “Composition over inheritance”. And composition plays very nicely with plain functions than classes. A lot , also has been said about why to avoid inheritance. From my experience, I too personally think, , inheritance should be avoided but I have nothing against languages that promote OOP and inheritance. Below are some good resources, notable one being for Golang, which is modern and practical, doesn’t have classes and encourages composition over inheritance. Same goes for Rustlang, no ‘class’ keyword! Also ‘swiftlang’ gives us ‘struct’ and ‘protocol oriented programming model’ to avoid classes and oop.

https://talks.golang.org/2012/splash.article#TOC_15.

Composition over inheritance: “Favor ‘object composition’ over ‘class inheritance’.” (Gang of Four 1995:20)

But often we want to have real life example instead of intellectual people’s heavy theories, isn’t it? :) So let’s see “composition over inheritance” in simple code. Here our ultimate aim is to share/reuse getInfo() functionality of “Person” . We will do it in three ways:

1) ES6 Clasess 2) Prototypal classes 3) Composition

Problem statement: Reuse getInfo() method/function of Person class/module in Employee class/module

  1. ES6 clasess:
class Person{
constructor(fn, ln){
this.firstName = fn;
this.lastName = ln;
}

getInfo(greetStr){
//In real life this method/function will be bigger
return `${greetStr}, I am ${this.firstName} ${this.lastName}.`
}
}
class Employee extends Person {
constructor(fn, ln, eid){
super(fn,ln);
this.empid = eid;
}

getId(greetStr){
return `${greetStr}, my employee id is ${this.empid}.`;
}
}
const e1 = new Employee('John', 'Doe', 123);console.log( e1.getInfo('Hi') );// Hi, I am John Doe.
console.log( e1.getId('Hello') ); // Hello, my employee id is 123.

2. Prototypal Classes:

function Person(fn, ln){
this.firstName = fn;
this.lastName = ln;
};

Person.prototype.getInfo = function(greetStr){
//In real life this method/function will be bigger
return `${greetStr}, I am ${this.firstName} ${this.lastName}.`
}

function Employee(fn, ln, empid){
Person.call(this, fn, ln);
this.empid = empid;
};

Employee.prototype = Object.create(Person.prototype);

Employee.prototype.getId = function(greetStr){
return `${greetStr}, my employee id is ${this.empid}.`;
}
var e1 = new Employee('John', 'Doe', 123);console.log( e1.getInfo('Hi') ); // Hi, I am John Doe.
console.log( e1.getId('Hello') ); // Hello, my employee id is 123.

3. Composition

//In real life getInfo method/function will be bigger
//So taking this function out of CreatePerson will make sense then
//and now it could be used to compose other functionality elsewhere
function getInfo(firstName, lastName, greetStr){
return `${greetStr}, I am ${firstName} ${lastName}.`
}
/**
Note that CreatePerson function is just shown here for demonstration. It's not referred/used in CreateEmployee and could be commented out
function CreatePerson(fn, ln){
return {
firstName: fn,
lastName: ln,
getInfo: (greetStr) => getInfo(fn, ln, greetStr)
};
}
*/

//In real life getId method/function will be bigger
//So taking this function out of CreateEmployee will make sense then //and now it could be used to compose other functionality elsewhere
function getId(empid, greetStr){
return `${greetStr}, my employee id is ${empid}.`;
}

//CreateEmployee makes use of composition. It's simple. Any function //which makes use of other functions to compose functionality is //said to be making use of composition. We all use it all the times.
function CreateEmployee(fn, ln, empid){
return {
empid: empid,
getId : (greetStr) => getId(empid, greetStr),
getInfo: (greetStr) => getInfo(fn, ln, greetStr)
};
}
var e1 = CreateEmployee('john', 'doe', 123);console.log( e1.getInfo('Hi') ); // Hi, I am John Doe.
console.log( e1.getId('Hello') ); // Hello, my employee id is 123.

See, first class functions and closures plays so well with javascript and we compose functionality with other functions. And now we can see that we don’t even need prototypal inheritance.

So the big question — Can we not do composition in other classical languages? — We can but its bit more code typing there since many languages can’t have function living independently out of classes (well, in php, ruby, python, kotlin etc can…but c#, java needs to have function/method inside class). So we need to create small classes having only one static method and then we can compose. Its demonstrated in following wikipedia article with C++:

So.. Show your class…by not using one! :)

Your comments, opinions are most welcome!

Note: I agree that closures needs bit more memory compared to prototype chains. In real life though, performance hits are very very small and negligible. A lot of JSPerf tests have shown that it would need millions of loose functions to actually realise that closures need bit more memory. In real life code there aren’t any performance hits (Of course unless you are writing compilers, databases and stuff like that :) )

Update (24, Oct ‘18): I edited article for small typos. Also I wanted to comment on Typescript since it’s very popular now and I too like it. Reason for using ‘Class’ in typescript is very different than using in JS. Because in typescript ‘Class’ is a type. if you do const p = new Person(‘John’); in typescript then p is of type Person and it is enforced/checked by compiler. But still when using typescript I tend not to use ‘class’ since typescript gives other powerful mechanism like ‘interface’ and ‘type’ to define types. I avoid class because the moment developer sees a class he can not resist temptation to put behaviour in class methods (instead of loose functions) and extend classes for inheritance. I did some kotlin and java recently and in kotlin we have good support of top level exportable/importable functions, so composition is encouraged and easy there. In java, I tend to use ‘class’ for representing data type with only properties and no methods and we can create separate static classes with static methods which acts on input data. This way, ‘data’ and ‘behaviour’ is separate and we can use ‘composition’ easily.

--

--