CLASSY

An introduction to ES6 classes

example

// Base class
class Animal {
    constructor({hasClaws}) {
        this._hasClaws = hasClaws;
    }
    hasClaws() {
        return this._hasClaws;
    }
}

// Derived class
class Cat extends Animal {
    constructor({hasClaws, purrs}) {
        super({hasClaws});
        this._purrs = purrs;
    }
    purrs() {
        return this._purrs;
    }
}

USAGE

const chaos = new Cat({hasClaws: true, purrs: true});

chaos.hasClaws();
chaos.purrs();

chaos instanceof Cat; // true
chaos instanceof Animal; // true
new Animal();     // ReferenceError

class Animal {
    
    prop: 6,                              // SyntaxError

    constructor({hasClaws}) {
        this._hasClaws = hasClaws;
    },                                    // SyntaxError
    
    ;                                     // ignored
    
    hasClaws() {                          // required syntax
        return this._hasClaws;
    }
}                                         // no semi-colon

typeof Animal     // "function" - just like an ES5 constructor function..
Animal();         // TypeError (but you have to use new)
new Animal();     // ✅

SAME SAME

(BUT DIFFERENT)

// anonymous
const Walrus = class Walrus {
    hasTusks(){
        return true;
    }
};
const wilfred = new Walrus();

// named
const Walrus = class Walrus {
    name(){
        return Walrus.name;
    }
};
const wilfred = new Walrus();
wilfred.name(); // 'Walrus'

expressions

const dynamic = 'methodName';

class Foo {
    constructor(prop) {
        this.prop = prop;
    }
    static staticMethod() {
        return 'classy';
    }
    prototypeMethod() {
        return 'prototypical';
    }
    [dynamic]() {
        return 'snazzy';
    }
}

const foo = new Foo(123);
Foo.staticMethod(); // 'classy'
foo.prototypeMethod(); // 'prototypical'
typeof foo.methodName; // 'function'

class methods

class Cat extends Animal {
    constructor({hasClaws, purrs}) {
        // note the change in syntax
        // super() only works in the constructor
        // you must call super before using this
        super({hasClaws});      
        this._purrs = purrs;
    }

    hasFur() {
        // here we must use super[prop]
        return super.hasFur() && !this.isSphinx;
    }
}

// The prototype of a subclass is the superclass:
Object.getPrototypeOf(Cat) === Animal; // true

sub-classes

It is an error to define a constructor in a derived class but leave it empty (not calling super).

THE FUTURE

class Cat extends Animal {   
    purrs = true;
    #hasFur;

    constructor({hasClaws, hasFur}) {
        super({hasClaws});
        this.#hasFur = hasFur;
    }
}

class fields

https://github.com/tc39/proposal-class-fields

mixins

// loudNoises is a function. Base is a variable, not an actual class
const loudNoises = Base => class extends Base {
    shout() { ··· }
    roar() { ··· }
    growl() { ··· }
};

class Cat extends loudNoises(Animal) {}

// This can keep going and going
class Cat extends climbsThings(movesQuickly(loudNoises(Animal))) {}

MIXINS

Mixins are not natively supported in ES6. There are a couple of different approaches we can use to implement them. This is the one we're going to use.

the end

ES6 Classes

By Helen Durrant

ES6 Classes

  • 310