Skip to content

Instantly share code, notes, and snippets.

@andrewdelprete
Last active December 31, 2017 16:23
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andrewdelprete/6d408d1e2e8c2184483f to your computer and use it in GitHub Desktop.
Save andrewdelprete/6d408d1e2e8c2184483f to your computer and use it in GitHub Desktop.
Learning to inherit with Javascript

Functional Inheritance

Basically a function in which you add additional functionality before returning it. Because the additional functionality is considered to be cloned from one function to another it doesn't matter if you inherit from a base / super function or some non-related function, it all works.

/**
 * friend(name)
 * Constructor Function - Must be instantiated to be used.
 */
var friend = function(name) { // Function Expression
    this.name = name,
    this.sayName = function() {
        console.log(this.name);
    };

    // 'this' receives the properties and methods from age() (mixin)
    age.call(this, this.age || 0);

    // return this (constructor functions return 'this' by default)
}

/**
 * age(int)
 * Constructor Function - Must be instantiated to be used.
 */
var age = function(int) {
    this.age = int;
    this.sayAge = function() {
        console.log(this.age);
    };
}

// The 'new' keyword - use sparingly, not recommended by many people.
var jaymes = new friend('Jaymes') 
jaymes.sayName(); // Jaymes
jaymes.age = 29;
jaymes.sayAge(); // 29

// apply() or call() - IS recommended
var colin = {};

friend.apply(colin, ['Colin']);
colin.sayName(); // Colin
colin.age = 29;
colin.sayAge(); // 29

Object Inheritance with Mixins

Object literals are like already instantiated singletons. They offer no privacy but when returned from a Factory Function can be very flexible.

var friend = {
	name: "John Doe",
	age: 42,
	sayName: function() {
		console.log(this.name);
	}
}

var sam = _.extend(friend, { name: "Sam", age: 32 }) 
sam.sayName(); // "Sam"

Factories

Factories provide a flexible way to create and return new objects. This is a common replacement for Constructor Functions and offers a number of benefits.

See 'Constructor Functions vs. Factory Functions' by Eric Elliot.

var friendProto = {
    name: null,
    age: null,
    sayName: function() {
        console.log(this.name);
    }
}

var friend = function(options) {
    var obj = _.extend(Object.create(friendProto), options)

    // Monkey patch sayName() method to increment counter every time it's called.
    (function() {
    	var counter = 0
    	var sayNameCopy = obj.sayName;
	    obj.sayName = function() {
	    	counter++
	    	console.log(counter)
	    	sayNameCopy.bind(this)
	    }

    }());

    return obj;
}

var tanner = friend({
    name: "Tanner",
    age: 'unknown'
})

tanner.sayName() // 1, Tanner

Twitter: andrewdelprete Github: pathsofdesign

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment