Blog

Home ►

Objects linked to other objects - Simplifies so much

Edit (2016-01-14): minor typography/style/bug/etc. fixes.

I recently made my first npm module (babel-plugin-proto-to-create), but this just stems from my general frustration with class-based OO. Not saying it's a terrible thing at all, or that I can't understand it at all, but there's nothing simpler than objects linked to other objects. Nothing more elegant than this:

const Vehicle = {
    new(make, model) {
        return {
            __proto__: this,
            make, model,
        }
    },

    toString() {
        return [
              "Type:  " + this.type,
              "Make:  " + this.make,
            "Model: " + this.model,
        ].join("\n")
    },
}

const Car = {
    __proto__: Vehicle,

    type: "Car",
}

const Truck = {
    __proto__: Vehicle,

    type: "Truck",
}

Merely creating an instance is as simple as this:

let car = Car.new("Nissan", "Ultima")

I really love the simplicity of this, pure prototypal OO. It's simple, concise, and beautiful. Or, if you'd prefer, you could always use ES6 classes:

class Vehicle {
    constructor(make, model) {
        this.make = make
        this.model = model
    }

    toString() {
        return [
              "Type:  " + this.type,
              "Make:  " + this.make,
            "Model: " + this.model,
        ].join("\n")
    }
}

class Car extends Vehicle {
    constructor(...args) {
        super(...args)
        this.type = "Car"
    }
}


class Truck extends Vehicle {
    constructor(...args) {
        super(...args)
        this.type = "Truck"
    }
}

Lot more boilerplate. Extending mixins in ES6 classes are also a little more complicated:

function mixin(Class, ...srcs) {
    class C extends Class {}
    Object.assign(C.prototype, ...srcs)
    return C
}

class Foo extends mixin(Bar, Baz) {}

// Or, if you want to mixin classes...

function mixin(Class, ...others) {
    class C extends Class {}
    Object.assign(C.prototype, ...others.map(D => D.prototype))
    return C
}

class Foo extends mixin(Bar, Baz) {}

Why do classes, even JS prototype-based classes, have to be so complicated?

function mixin(Type, ...others) {
    return Object.assign({__proto__: Type}, ...others)
}

const Foo = {
    __proto__: mixin(Bar, Baz),
}

And with ES7's object spread operator, the mixin picture is only going to make this nicer:

const Type = {
    __proto__: Foo,
    ...Mixin1,
    ...Mixin2,

    method() {},
}

Very lightweight mixins that don't need any syntactical support. Not to mention you could even define these is-a/has-a relationships conditionally at object creation time:

const Type = {
    new(condition) {
        return {
            __proto__: this,
            ...(condition ? Mixin1 : Mixin2),
        }
    }
}

I know of no other language with this kind of flexibility.