Does JavaScript need classes?
Like it or not, ECMAScript 6 is going to have classes[1]. The concept of classes in JavaScript has always been polarizing. There are some who love the classless nature of JavaScript specifically because it is different than other languages. On the other hand, there are those who hate the classless nature of JavaScript because it’s different than other languages. One of the biggest mental hurdles people need to jump when moving from C++ or Java to JavaScript is the lack of classes, and I’ve had people explain to me that this was one of the reasons they either didn’t like JavaScript or decided not to continue learning.
JavaScript hasn’t had a formal definition of classes since it was first created and that has caused confusion right from the start. There are no shortage of JavaScript books and articles talking about classes as if they were real things in JavaScript. What they refer to as classes are really just custom constructors used to define custom reference types. Reference types are the closest thing to classes in JavaScript. The general format is pretty familiar to most developers, but here’s an example:
function MyCustomType(value) {
this.property = value;
}
MyCustomType.prototype.method = function() {
return this.property;
};
In many places, this code is described as declaring a class named MyCustomType. In fact, all it does is declare a function named MyCustomType that is intended to be used with new to create an instance of the reference type MyCustomType. But there is nothing special about this function, nothing that says it’s any different from any other function that is not being used to create a new object. It’s the usage of the function that makes it a constructor.
The code doesn’t even look like it’s defining a class. In fact, there is very little obvious relationship between the constructor definition and the one method on the prototype. These look like two completely separate pieces of code to new JavaScript developers. Yes, there’s an obvious relationship between the two pieces of code, but it doesn’t look anything like defining a class in another language.
Even more confusing is when people start to talk about inheritance. Immediately they start throwing around terms such as subclassing and superclasses, concepts that only make sense when you actually have classes to work with. Of course, the syntax for inheritance is equally confusing and verbose:
function Animal(name) {
this.name = name;
}
Animal.prototype.sayName = function() {
console.log(this.name);
};
function Dog(name) {
Animal.call(this, name);
}
Dog.prototype = new Animal(null);
Dog.prototype.bark = function() {
console.log("Woof!");
};
The two-step inheritance process of using a constructor and overriding a prototype is incredibly confusing.
In the first edition of Professional JavaScript for Web Developers, I used the term “class” exclusively. The feedback I received indicated that people found this confusing and so I changed all references to “class” in the second edition to “type”. I’ve used that terminology ever since and it helps to eliminate a lot of the confusion.
However, there is still a glaring problem. The syntax for defining custom types is confusing and verbose. Inheritance between two types is a multistep process. There is no easy way to call a method on a supertype. Bottom line: it’s a pain to create and manage custom types. If you don’t believe that this is a problem, just look at the number of JavaScript libraries that have introduced their own way of defining custom types, inheritance, or both:
- YUI – has
Y.extend()to perform inheritance. Also adds asuperclassproperty when using this method.[2] - Prototype – has
Class.create()andObject.extend()for working with objects and “classes”.[3] - Dojo – has
dojo.declare()anddojo.extend().[4] - MooTools – has a custom type called
Classfor defining and extending classes.[5]
It’s pretty obvious that there’s a problem when so many JavaScript libraries are defining solutions. Defining custom types is messy and not at all intuitive. JavaScript developers need something better than the current syntax.
ECMAScript 6 classes are actually nothing more than syntactic sugar on top of the patterns you are already familiar with. Consider this example:
class MyCustomType {
constructor(value) {
this.property = value;
}
method() {
return this.property;
}
}
This ECMAScript 6 class definition actually desugars to the previous example in this post. An object created using this class definition works exactly the same as an object created using the constructor definition from earlier. The only difference is a more compact syntax. How about inheritance:
class Animal {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
bark() {
console.log("Woof!");
}
}
This example desugars to the previous inheritance example. The class definitions are compact and the clunky multistep inheritance pattern has been replaced with a simple extends keyword. You also get the benefit of super() inside of class definitions so you don’t need to reference the supertype in more than one spot.
All of the current ECMAScript 6 class proposal is simply new syntax on top of the patterns you already know in JavaScript. Inheritance works the same as always (prototype chaining plus calling a supertype constructor), methods are added to prototypes, and properties are declared in the constructor. The only real difference is less typing for you (no pun intended). Class definitions are just type definitions with a different syntax.
So while some are having a fit because ECMAScript 6 is introducing classes, keep in mind that this concept of classes is abstract. It doesn’t fundamentally change how JavaScript works; it’s not introducing a new thing. Classes are simply syntactic sugar on top of the custom types you’ve been working with for a while. This solves a problem that JavaScript has had for a long time, which is the verbosity and confusion of defining your own types. I personally would have liked to use the keyword type instead of class, but at the end of the day, this is just a matter of semantics.
So does JavaScript need classes? No, but JavaScript definitely needs a cleaner way of defining custom types. It just so happens the way to do that has a name of “class” in ECMAScript 6. And if that helps developers from other languages make an easier transition into JavaScript, then that’s a good thing.
Translations
References
- Maximally minimal classes (ECMA)
- YUI extend() (YUILibrary)
- Prototype Classes and Inheritance (Prototype)
- Creating and Enhancing Dojo Classes (SitePen)
- MooTools Class (MooTools)
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, O'Reilly Publishing, or anyone else. I speak only for myself, not for them.
Both comments and pings are currently closed.




40 Comments
I really can’t see any drawbacks by adding classes to JavaScript. Especially if you can still use the old syntax to create custom objects. I welcome this addition.
José on October 16th, 2012 at 8:27 am
Nice article! What about multiple inheritance ?
Guillaume Cisco on October 16th, 2012 at 8:44 am
At BrazilJS couple months ago I’ve asked both Dave Herman (member of W3c TC39 ES6 team) and he assured me that the Class keyword is only syntactic sugar, not a real Class implementation.
And Mr Brendan Eich reassured that the next day, so I’m glad to reinforce your last couple paragraphs, that JS is not going to be a CLASSical language, but will have some sugar for CLASSical people
Mauricio Wolff on October 16th, 2012 at 9:07 am
@Guillaume – multiple inheritance doesn’t exist in JavaScript (or many other languages).
Nicholas C. Zakas on October 16th, 2012 at 9:14 am
It’s really nice article, good job! But I would used the term constructor (or just construct) instead of type. Also it would be good to mention these classes are already implemented in TypeScript and they just compile to normal ES 5 syntax.
Radomír Žemli?ka on October 16th, 2012 at 9:39 am
I still remind when Flash switched from AS1 to AS2, it was basically the same thing. Sugar on top of the prototypical inheritance without changing scope rules and without changing the way code was executed. It was a good improvement for code organization but it still didn’t solve one of the biggest issues of the language, scope. The `this` keyword is one of the biggest strengths of JS/AS when you think about code reuse (since you can use `Function#call` and `Function#apply` to change the context) but it is also one of the most misunderstood features. The current class system proposal doesn’t solve `this` issue. People coming from other languages will still have a hard time figuring out why there is a `TypeError: foo.bar.ipsum is undefined` when calling an instance method.
Another “problem” with the Maximally Minimal Classes is that it doesn’t specify a way to set shared properties among all instances without accessing the `Animal.prototype` outside the Class body. Static properties are also added outside the Class body. This will feel weird to people coming from other languages as well, code will still be scattered across multiple places. You will still have issues with people relying on `typeof` and `instanceof` to check if a given instance is of the correct type, etc… Why not go the whole mile and add the `static` keyword and “shared” properties to the class body? Why not kill the `this` keyword altogether and move the instance properties to the class body like regular `var` declarations?
If `Object.create()` wasn’t so verbose when adding custom properties (similar to all libs listed above) it could totally replace the need of constructor functions and classes. I guess ES5 missed the opportunity to make it truly useful.
I guess the question should really be: do I really need inheritance? why do you need instances/classes/inheritance? shouldn’t we be using JS more as a functional language?
I like the addition of a cleaner syntax (I would totally use it), I just don’t see that many benefits for people who doesn’t get how prototypical inheritance works and specially how the `this` keyword works. I would rather see something like Haxe Classes which resolve context automatically following a logical way (ignore type annotations, they are optional anyway).
PS: with AS3 the `this` keyword was made optional and scope was automatically bound to the proper context during the instance creation (similar to Haxe), that made development way easier. Imagine a world without the need of `Function#bind`. Things just work™
PPS: I really like @izs post about the Evolution of a Prototypal Language User, same happened with me.
Cheers.
Miller Medeiros on October 16th, 2012 at 9:44 am
@Radomir – a constructor is just a function. The type represents a grouping of data. You can create an instance of a type by using a constructor. These are very different terms.
Nicholas C. Zakas on October 16th, 2012 at 9:47 am
@Nicholas – Yes, I agree. But first you define the constructor. It’s the function that containts the prototype property. And it’s the most important thing, because you can’t define the type without the constructor. When you make new instance it is an object which refers to the prototype. So the type itself is the prototype, not the function (or class).
Radomír Žemlicka on October 16th, 2012 at 9:56 am
I don’t agree that semantics is *just* a matter of semantics, and think that the choice of the word “class” is quite unfortunate.
P. Envall on October 16th, 2012 at 10:34 am
@Petter – I’m sorry, I just can’t stop giggling over, “I don’t agree that semantics is just a matter of semantics”
Nicholas C. Zakas on October 16th, 2012 at 11:04 am
I’m one of the people who thinks it’ll be nice when it arrives. But it won’t become useful until it’s supported by all the browsers we need to develop for. In the meantime, I use this:
In the meantime, I use this: http://jsfiddle.net/gnJcP/. Short, simple, powerful.
Jeff on October 16th, 2012 at 11:06 am
Heh, meta stuff is (almost) always entertaining
I aim to please.
P. Envall on October 16th, 2012 at 11:12 am
Given the current awful function.prototype syntax, the class syntax is a big improvement.
But still I wish Javascript will just have a better way of working with prototypes. In my option IO got this right from the beginning. In pseudo JS syntax it would look something like this:
var Animal = {}
var Cat = Animal.clone({
init: function () {}
})
var cat = Cat.new();
Many JS libraries implement something like this. but having this in JS core in the first place would be sweet.
Sebastian on October 16th, 2012 at 1:40 pm
Hello Nicholas,
You wrote that methods are added to prototypes, and properties are declared in the constructor.
Is not possible with the new ECMAScript 6 class definition define an own method (in the constructor not in the prototype)?
@arleytriana
Arley on October 16th, 2012 at 3:27 pm
The zoo of different ‘class’ implementations has always confused me. I never felt like I fully grasped the topic even if I understood specific class implementations. In some way it felt like I had to understand all possible ways to implement classes in javascript, not just one.
So yes, you struck a nerve when you mentioned the confusion about classes,… er types, that exists today. Thank you for explaining the topic so clearly and I am now definitely onboard with the ES6 class syntax!
Remco Veldkamp on October 16th, 2012 at 3:36 pm
JS does need classes. But sure it already has.
OOP entity that acts like class – is a class. No matter how you call it – a “constructor/prototype pattern”, or anything else.
Some people in comments say that JS is functional language, but that is not true. Learn you a Haskell and you see the difference.
Being neither a functional, nor an OOP language JS would seem to be poor language itself, but i believe it is not. So let it have at least classes.
?commie? on October 17th, 2012 at 12:35 am
Thanks for sharing.
“ECMAScript 6 classes are actually nothing more than syntactic sugar on top of the patterns you are already familiar with. …:”
Which means that to write proper (good) JavaScript, the best thing to do (and even with EcmaScript6) would be to actually know JavaScript and still use prototypes, I agree that it’s a nice addition in terms of syntax, but it’s always better to undertstand how things *really* work
justadude on October 17th, 2012 at 2:14 am
So is there a shim available or are we going to have to write it the old way for years and years anyway until ECMA 6 is in all browsers?
Brent Cowgill on October 17th, 2012 at 9:14 am
@justadude – I disagree with that sentiment. Yes, it’s nice to have a deeper understanding of how things work, but I don’t think it should be a requirement.
Nicholas C. Zakas on October 17th, 2012 at 9:41 am
@Brent – You could use TypeScript, which supports ES6-style classes, or Traceur, which is an ES6-to-ES5 transpiler.
Nicholas C. Zakas on October 17th, 2012 at 9:42 am
@Arley – Yes, you can add methods in the constructor if you want to.
Nicholas C. Zakas on October 17th, 2012 at 9:43 am
@Commie – JavaScript doesn’t have classes, as classes have several unique characteristics such as locking-in the interface of an object. JavaScript has something that performs logical grouping of data and functionality that is similar to classes, but it’s not the same.
Nicholas C. Zakas on October 17th, 2012 at 9:44 am
Hi, you said that “.. Class definitions are just type definitions with a different syntax. …” so is it real new type definition above EcmaScript types: Boolean, String, Number, Object, null and undefined ? What about typeof operator then? Will it be true:
class MyClass {
//…
}
var instance = new MyClass()
instance typeof “MyClass”; // >>> true
Max Podriezov on October 19th, 2012 at 5:18 am
@Commie,,
“OOP entity that acts like class – is a class. No matter how you call it – a “constructor/prototype pattern”, or anything else.”
That is simply not true. JavaScript adopted the Prototypical inheritance model from Self (albeit not as well implemented – Self makes this much easier to express). The key difference is that any object can be a prototype, while a class is either (i) something that is used at compile-time (C++, Eiffel, Java) and cannot be altered thereafter, or (ii) an instance of a class Class (Smalltalk, C’#).
The Prototypical model is actually more expressive – for example Self builds a complete Smalltalk-80 environment with minimal code, simply by introducing objects that fulfil the role of ST-80 classes. To do the opposite would involve creating a whole new structure for objects, message dispatch, etc. and would be a much harder task.
Rob G on October 19th, 2012 at 6:02 am
@Nicholas,
“Classes have several unique characteristics such as locking-in the interface of an object”
that’s not strictly true. In Smalltalk (and many other languages), methods can be added to a class at runtime.
Rob G on October 19th, 2012 at 6:03 am
The concept of classes and inheritance isn’t really why I don’t even use the new operator with prototypical inheritance… But rather the lack of functionality to define access to your data. Once you add anything to ‘this’, everyone has access to your data!
I agree inheritance is great and all that, but as the author of this post mentions, this isn’t really new to JavaScript. So, more importantly I would prefer to see data access protection so that I can more confidently use any type of classes/inheritance, regardless of sugar syntax. Module pattern is how do my JavaScript magic to easily and successfully hide data from people consuming my code; love that pattern and it fits really well with the weakly typed nature of JavaScript.
How good would Java/C++ be with their classes/inheritance when everything is public? You would be missing half of the story here.
good reference: JavaScrict design patterns
Miguel on October 19th, 2012 at 6:04 am
Nice article.
As you point out JavaScript already has classes in the form of constructor/prototype chains. The bigger debate might be does JavaScript need constructor/prototype chains – are they a natural language fit, or are they a gnarly tick to replicate classical inheritance in a language that doesn’t need it?
Traditional OOP languages need inheritance hierarchies in order to re-use functionality because their methods are only visible to members of the hierarchy. JavaScript has a dynamic ‘this’ keyword (which enables property copy mixins) and call/apply (which allows for functional mixins – functions that assign behavior to whichever context they are applied to) which significantly diminishes the importance of inheritance hierarchies.
I find mixins more flexible and less constraining than class hierarchies – in the latter case we must establish abstract supertypes upfront – with mixins we have time to play and experiment with the problem, start with concrete types and allow abstractions (mixins) to evolve as we recognize common behavior.
I’d also suggest mxins are more in keeping with the prototypal spirit which is about identifying functional alikeness as opposed to imposing a rigid (and often tenuous) “is-a” realtionship on things that really “isn’t a”
In a nutshell – yes the class syntax will pave the constructor/prototype cow path. Question is – is that we want to lead the cows?
Angus Croll on October 19th, 2012 at 6:14 am
I definitely prefer using the keyword “type” instead of “class”
It keeps JavaScript unique… because it’s not java and it shouldn’t have to be ugly like java!
Stephen Bussard on October 19th, 2012 at 7:03 am
totally agree with Angus plus, to those saying `this` is the problem with classes methods, `this` is actually the most powerful thing JavaScript has when it comes to reusability and mixins.
As a concept I don’t think `this` is that difficult to understand and I’ve always wonder why CLASSical developers do not even try to understand the difference being slightly open minded about a different approach … and it looks to me everyday more developers familiar with prototypal inheritance are able to code with any sort of programming language but it’s not always the case with CLASSical developers: “no classes? that ain’t a language” … surely this is just my impression thought and btw, nice post
Andrea Giammarchi on October 19th, 2012 at 9:02 am
@Max – no, you’re talking about primitive types. This is a new reference type which
typeofalways identifies as “object”.Nicholas C. Zakas on October 19th, 2012 at 9:27 am
I hope that they will standardise __proto__ in ES6, I don’t feel like dealing with multiple levels of abstraction layers when building inheritance chains. With plain object literals, __proto__ and call()/apply()/bind() you can already create class-like relationships between objects, but you can also easily build prototypical hierarchies, mixins or delegates.
Jarek Foksa on October 19th, 2012 at 10:08 am
@Jarek – it’s already been approved.
Nicholas C. Zakas on October 19th, 2012 at 10:31 am
JavaScript has classes, if we look at functionality, not terminology. Constructors (including the properties thereof, which includes one especially cool property named ‘prototype’) provide benefits very like those of classes in the limited OOP fork started by Stroustrup, then Gosling. They had classes that were not objects and were very limited. Thank goodness JS doesn’t have non-objects to hem us in.
I did a little comparison of the class-substitute code by Crockford, Flanagan, Resig and Edwards. It also uses plain JS for a baselne. Executive summary: JS alone doesn’t need much help.
http://martinrinehart.com/frontend-engineering/engineers/javascript/inher/masters/master-inheritance-comparison.html
A longtime Java guy, I’ve come to embrace the GoF’s dictum: composition, not inheritance. OOP can live nicely without inheritance. JS can do inheritance nicely in the rare cases where it’s a good idea., See my “Eich” code, above link.
Martin Rinehart on October 19th, 2012 at 11:23 am
I think ‘class’ and ‘type’ could be misunderstood as well, because most of us consider ‘classes’ to be custom defined types with access attributes (private,public,abstract etc) as they are in Java, C++ – class inheritance languages. On the other hand JavaScript has its uniqueness by its prototypes and dynamic nature. The ‘type’ keyword could be understand in JavaScript to be one of the basic general types in EcmaScript, those are: Boolean, String, Object, Null, Undefined. You can find it in EcmaScript spec. at page 28, p. 8:
” An ECMAScript language type corresponds to values that are directly manipulated by an ECMAScript programmer using the ECMAScript language. The ECMAScript language types are Undefined, Null, Boolean, String, Number, and Object. ”
We all feel need to have such thing as ‘classes’ but in ‘JavaScript’ way, to not break its nature. I would like to call it with ‘define’ keyword, like this:
define Name {
var prop = “some property”;
constructor() {}
method() {}
//…
}
//and extension
define Other extends Name {
}
Max Podriezov on October 19th, 2012 at 11:41 am
The problem with JavaScript classes is that they have nothing to do with the concept of classes in other languages – which makes them confusing especially for those who are afraid to charter the JavaScript world.
The real problem with JavaScript is that it’s a language that was never meant to do what it’s currently doing.
Fadi El-Eter (itoctopus) on October 19th, 2012 at 12:45 pm
Prototypal inheritance provides no clean way to grab a reference to “super” (via a generic accessor) and simply pass the message up the prototype chain. If it could do that prototypal inheritance might be a little more attractive.
Mario T. Lanza on October 19th, 2012 at 3:05 pm
@Guillaume multiple inheritance ? easy…
var Emitter = function () {};
var Page = function () {}
var Foo = function () {
Page.call(this);
Emitter.call(this);
}
for (var k in Emitter.prototype) foo.prototype[k] = Emitter.prototype[k];
for (var k in Page.prototype) foo.prototype[k] = Page.prototype[k];
yields on October 20th, 2012 at 2:42 pm
Nice, I think it’s better to add qooxdoo and emberJS object model to the list, for qooxdoo it has its owan way to add inheritance, Interfaces and even mixins what about, emberJS has mixins too, the aim of this is to have a way to make multiple inheritance in javascript. I dont know ECMAScript6 yet but it’s nice if JS will have at list mixins or interfaces.
Mohamed Cherif BOUCHELAGHEM on October 22nd, 2012 at 12:09 am
It’s certainly a nice addition for version 6. I imagine it will make the class-related JS generated by my CoffeeScript compiler easier to look at.
Tony on October 22nd, 2012 at 3:41 am
@yields – That’s not multiple inheritance. You’ve broken
instanceof.Nicholas C. Zakas on October 24th, 2012 at 3:38 pm
Comments are automatically closed after 14 days.