Inheritance patterns in JavaScript

(by way of a brief history of music)

Classical

Inheritance
In JavaScript



class Blues {
  constructor () {
    this.genre = 'Blues'
    this.dance = 'Blues Dancing'
  }

  get instruments() { return [
        'guitar',
        'trumpet',
        'standup bass',
        'drums'
    ]
  }
}

var bbKing = new Blues()

bbKing.dance // 'Blues Dancing'

A Classic class

class Definition

class Blues {

  constructor (...constructorArgs) {
    this.someInstanceProperty = `You can't inherit me`
    this.someOtherInstanceProperty = constructorArgs[0]
  }

  someMethodOnThePrototype() { ... }

  get somePropertyOnThePrototype() {
    // Access me like a class property
    // ( myInstance.somePropertyOnThePrototype //-> 4 )
    return 4
  }

  set somePropertyOnThePrototype(val) {
    // Assign to me like a class property
    // ( myInstance.somePropertyOnThePrototype = 4 )
    this.somePropertyOnThePrototype = val
  }
}
const bbKing = new Blues();

Object Instantiation

How about a new class that inherits from Blues?

A Jazzy Class



class Jazz extends Blues {
  constructor () {

    this.genre = 'Jazz'
    this.dance = 'groove'
  }
}



const milesDavis = new Jazz()

milesDavis.genre // Jazz

milesDavis.instruments // ['guitar', 'trumpet', 'standup bass', 'drums']

(pseudo)Classical Inheritance in Javascript

Boom

... but ...

This Is

Just A
Façade

Javascript
is not A Classical Language

Class are sugar around a restricted form of prototypal inheritance

 

Classes are objects in JavaScript. They are referenceable, and mutable.

 

There is (currently) no way to "declare" a private variable within the class.

 

Absent the `class` sugar, classes are simple functions called with the `new` keyword. 

Classical Inheritance in JavaScript is Actually pseudo-Classical Inheritance

"The ​pesudoclassical form can provide comfort to programmers who are unfamiliar with JavaScript, but it also hides the true nature of the language."

 

-Douglas Crockford

Classical Inheritance in JavaScript is dumbed down prototypal inheritance

SPEAKING OF PROTOTYPAL INHERITANCE

ALL OBJECTS IN JAVSCRIPT inherit from a PROTOTYPE

THE PROTOTYPE

rock = {};

/*
    {
        __proto__: {...}
    }
*/

ROck INHERITANCE

const rock = {
    instruments: [
        'electric guitar',
        'bass',
        'drums',
    ],
    
    genre: 'Rock',
    dance: 'Fist Pump'
};


const theWho = Object.create(rock);

theWho.dance = 'Jump';
const theWho = Object.create(rock);

Here we tell JavaScript to create a new object with rock as its prototype.

What it looks like

{
    dance: 'Jump'

    __proto__: {
        instruments: [
            'electric guitar',
            'bass',
            'drums'
        ],

        dance: 'Fist Pump',
        genre: 'Rock'
    }
}

PROTOtypes are dynamic SO WE CAN ADD TO THEM

ADD SOME KEYBOARD and volume

rock.volume = 10;
rock.instruments.push('keyboard');


/*
    theWho.volume // 10
    theWho.instruments // [ 'electric guitar', 'bass', 'drums', 'keyboard']

*/
theWho.__proto__.volume = 11;

/*
    rock.volume // 11
    theWho.volume // 11

*/

Functional Composition in JavaScript

JavaScript is a Functional Language

The Humble Object

const milesDavis = {}

with properties

const milesDavis = {
    genre: 'Jazz',
    instruments: [
        'guitar',
        'trumpet',
        'standup bass',
        'drums'
    ]
}

and methods

const milesDavis = {
    genre: 'Jazz',
    instruments: [
        'guitar',
        'trumpet',
        'standup bass',
        'drums'
    ],

    dance: () => 'Groove'
}

Cool!

Let's make something that Does stuff to it.

bigbandinator Function

const bigBandinator = ({ instruments = [], ...objectIn }) => ({
    ...objectIn,
    instruments: [...new Set([
        'drums',
        'trumpets',
        'trombones',
        'saxophones',
        'standup bass',
        ...instruments || []
    ])],
    dance: 'Charleston',
    genre: 'Big Band'
})

bigbandinate Mr Davis

const glenMillerOrchestra = bigBandinator(milesDavis)

/*
{
    genre: 'Big Band',
    dance: 'Charleston',
    instruments: [
        'drums',
        'trumpets',
        'trombones',
        'saxophones',
        'standup bass'
    ]
}
*/

We have achieved functional inheritance

Cool!

But what if we "inated" multiple Objects?

bigband

+ Punk

How about a Punk ojbect?

const ramones = {

    genre: 'Punk',

    dance: 'mosh',

    instruments: [
        'drums',
        'electric guitar',
        'bass'
    ]
}

We need a punkinator

Let's Make it an Inator

const punkinator = ({ instruments=[], ...objectIn }) => ({
    ...objectIn,
    instruments: [...new Set([
        'drums',
        'electric guitar',
        'bass',
        ...instruments
    ])],

    dance: 'Mosh',
    genre: 'Punk'

})

Behold, the birth of SKA!

const skainator = (objectIn) => ({

    ...bigBandinator(objectIn),

    ...punkinator(objectIn),

    genre: 'Ska',
    dance: 'Skank'
})

The Ska Robot Army

const aquaBats = {
    members: {
        "Christian Jacobs": "MC Bat Commander",
        "Matt Von Gundy": "Gumby",
        "Ben Bergeson": "Ben the Brain",
        "Charles Gray": "Mysterious Kyu",
        "Chad Larson": "Crash McLarson",
        "Chad Parkin": "Nacho",
        "Rod Arellano": "Roddy B.",
        "Boyd Terry": "Catboy",
        "Adam Deibert": "Prince Adam",
    }
}

skainator(aquaBats)

The Fury of the Aquabats

{
    members: {
        "Christian Jacobs": "MC Bat Commander",
        "Matt Von Gundy": "Gumby",
        "Ben Bergeson": "Ben the Brain",
        "Charles Gray": "Mysterious Kyu",
        "Chad Larson": "Crash McLarson",
        "Chad Parkin": "Nacho",
        "Rod Arellano": "Roddy B.",
        "Boyd Terry": "Catboy",
        "Adam Deibert": "Prince Adam",
    },
    
    instruments: [
        'drums',
        'electric guitar',
        'bass'
        'trumpets',
        'trombones',
        'saxophones',
        'standup bass'],

    genre: 'ska',
    dance: 'skank'
}

You have been inated

Classical Inheritance

By Cory Brown

Classical Inheritance

  • 2,204