ES6 Class Inheritance vs. VanillaJS Prototypical Inheritance of Class-Level Objects

Recently I was working on building a DoJo-based widget (DoJo 1.X uses VanillaJS in the background) and I've spent a lot of time trying to figure out why a globally-defined array is getting updated across different instances of that widget. 

This gif describes exactly what was happening, in a more kid-friendly format...

Debugging

DoJo-specifics aside, what everything came down to is the way that VanillaJS handles class inheritance. JavaScript pre-ES5 uses prototypical inheritance to create classes, that meant that if a parent had a globally-defined object, every child created from that parent would actually just reference the parent's object. 

//There's different kinds of vehicles
var Vehicle = function() {};
//All of which consist of parts
Vehicle.prototype.parts = [];

//Some are cars
var Car = function() {
  return new Vehicle();
}

//Others are bikes
var Bike = function() {
  return new Vehicle();
}

//You buy a car and a bike
var myCar = new Car();
var myBike = new Bike();

for(part = 0; part < 1500; part++) {
  myCar.parts.push(part);
}

for(part = 0; part < 30; part++) {
  myBike.parts.push(part);
}

//When you do repairs on your car, you expect 1500 parts
var parts = myCar.parts.length ;
//Somehow, your car has 1530. ES5 easter egg!

ES6 and later fixes this issue with the Class syntax.

class Vehicle {
  constructor() {
    this.parts = [];
  }
}

class Car extends Vehicle {
  constructor() {
    super();
    this.engineVolume;
  }
}

class Bike extends Vehicle {
  constructor() {
    super();
    this.bikeType;
  }
}

var myCar = new Car();
var myBike = new Bike();

for(part = 0; part < 1500; part++) {
  myCar.parts.push(part);
}

for(part = 0; part < 30; part++) {
  myBike.parts.push(part);
}

var parts = myCar.parts.length ;
//parts will be 1500 - what we would expect

To many, this paradox resulting from prototypical inheritance might be common sense, but it's easy to forget about nuances as such when working in a framework that attempts to abstract away from JavaScript's true nature. 

Takeaway: don't blindly trust the framework to do what you expect it to do without an understanding of what happens behind the scenes. 

JSFiddle Example 

Dojo's Declare Documentation - "Classy JavaScript with dojo/_base_declare"