Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

A Matter of Class

DZone's Guide to

A Matter of Class

If a programming language contains classes, it's an object-oriented language, right? In JavaScript world, that's not really the case.

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

Introduced by the ECMAScript 2015 specifications, the class construct has become part of the official JavaScript syntax. This construct has been enthusiastically welcomed by many developers. Indeed, it has been considered a sign of the formalization of various attempts to simulate classes, inheritance, and other object-oriented features offered for several years by many libraries, such as PrototypeExtJSDojoBackboneEmber, and others. TypeScript itself was born with the aim of bringing class-based object-oriented programming to the JavaScript language. However, the class construct may lead to serious misconceptions about the object-oriented nature of JavaScript. Let’s analyze why.

A Convenient Construct

Using the class construct is very handy. Just take a look at the following code to define the Animal class:

class Animal {
  constructor(name, legsNumber) {
    this.name = name;
    this.legsNumber = legsNumber;
  }

  speak() {
    console.log(this.name + ‘ makes a noise.’);
  }
}

Now let’s compare it with the equivalent ECMAScript 5 code:

var Animal = function (name, legsNumber) {
  this.name = name;
  this.legsNumber = legsNumber;
};

Animal.prototype.speak = function() {
  console.log(this.name + ‘ makes a noise.’);
};

The class construct provides a much more compact code. It appears self-contained and familiar to people who have a traditional object-oriented programming background.

The convenience of this construct becomes even more noticeable when we use inheritance, as we can see by analyzing the following code where the Snake and Horse classes are defined by deriving from Animal:

class Snake extends Animal {
  constructor(name: string) {
    super(name, 0);
  }

  speak() {
    console.log(this.name + ‘ hisses.’);
  }
}

class Horse extends Animal {
  constructor(name: string) {
    super(name, 4);
  }

  speak() {
    console.log(this.name + ‘ whinnies.’);
  }
}

Let’s consider now the respective definitions with the dear old ECMAScript 5:

var Snake = function (name) {
  Animal.apply(this, [name, 0]);
};

Snake.prototype = Object.create(Animal.prototype);
Snake.prototype.constructor = Snake;
Snake.prototype.speak = function() {
  console.log(this.name + ‘ hisses.’);
};

var Horse = function (name) {
  Animal.apply(this, [name, 4]);
};

Horse.prototype = Object.create(Animal.prototype);
Horse.prototype.constructor = Horse;
Horse.prototype.speak = function() {
  console.log(this.name + ‘ whinnies.’);
};

The convenience of using the class construct seems clear: in addition to a smaller number of statements, we get a greater readability and a similarity to the syntax of most object-oriented programming languages. Anyway, regardless of the definition used, in both cases, we will use the classes and constructor functions in the same way:

var kaa = new Snake(“Kaa the Python”);
var fury = new Horse(“Fury the Horse”);

console.log(kaa.legsNumber);    //0
console.log(fury.legsNumber);   //4

This ensures the maximum interoperability between the old and the new approach.

Not Everyone Is Happy

Despite its convenience, however, not all developers are so excited about the introduction of the class construct. It looks familiar to most programmers and gives the illusion of using a class-based object-oriented programming language such as Java and C#.

But that is the whole point: it is an illusion, a dangerous illusion. Contrary to what might seem, ECMAScript 2015 specifications have not introduced the concept of class in JavaScript. JavaScript is, and remains, a prototype-based object-oriented programming language, even with the class construct.

The introduction of this construct in JavaScript syntax seems to extend the chain of errors that characterized the definition of this language: from the choice of the name itself, that has caused (and still causes) a bit of confusion with Java, to the use of the new keyword to create objects, actively contested by Douglas Crockford.

The main effect of these choices is that programmers are misguided in the real understanding of the language and are led to blame it because its behavior is not what is expected.

Is it a Real Class?

But what is the difference between the class construct in class-based languages and the one in JavaScript? As we said, JavaScript is still a prototype-based language, so the class construct is just syntactic sugar for creating constructor functions in a more compact way. If we try to get the type of a class, we will find that it is not but a function:

console.log(typeof Animal);   //function

The definition of AnimalSnake, and Horse, by using the class construct, has the same effect of its definition by using the old ECMAScript 5-style code. Objects are not created by referencing a class, but by referencing a prototype, that is another object, as usual in JavaScript. This means that we can dynamically change the structure of our objects without involving its original class. For example, we can write the following code:

fury.wingsNumber = 2;

console.log(fury instanceof Horse);   //true

We add a couple of wings to our Horse object, and it continues to be a horse. That’s perfectly legal in JavaScript, but it is very difficult to implement and to understand in a class-based world.

Even worse, we can overturn the whole structure of our Horse object as follows:

var furySnake = new Horse();

furySnake.legsNumber = 0;
furySnake.speak = function() {
  console.log(this.name + ‘ hisses.’);
};

We have redefined the structure of a Horse as if it were a Snake, but it still remains an instance of the Horse class. That’s out of any definition of class, not only in the context of programming languages but also in philosophy and set theory contexts.

For example, from a mathematical point of view, a class is a collection of objects that can be unambiguously defined by one or more properties that all its member share. Clearly, since fury and furySnake share no properties, they cannot belong to the same (conceptual) class. Also, from a class-based object-oriented point of view, the two objects can’t belong to the same class.

Conclusion

Maybe the choice of a name other than class would have sounded strange to developers coming from languages like Java, C#, and C++, but it would have created fewer illusions and disappointments.

In any case, now the die is cast. The important thing is that the JavaScript developer is aware of what class really means. You have been warned.

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:
javascript ,web dev ,object oriented ,classes ,prototypal inheritance in javascript

Published at DZone with permission of Andrea Chiarelli. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}