Skip to content

Instantly share code, notes, and snippets.

@marlun78
Last active August 29, 2015 14:06
Show Gist options
  • Save marlun78/cee41dd1cdaff01b3aba to your computer and use it in GitHub Desktop.
Save marlun78/cee41dd1cdaff01b3aba to your computer and use it in GitHub Desktop.
JavaScript prototypal inheritance
/**
* Class.js
* JavaScript prototypal inheritance
* Copyright (c) 2014 marlun78
* MIT License, https://gist.github.com/marlun78/bd0800cf5e8053ba9f83
*
* @example:
* function Person(name) {
* this.name = name;
* }
*
* Person.prototype.greet = function greet() {
* console.log('Hello, my name is', this.name);
* };
*
* function Child(name) {
* this.super(name);
* }
*
* Child.extends(Person); // or Class.extends(Child, Person);
*
* var martin = new Person('Martin');
* martin.greet(); // Hello, my name is Martin
* martin instanceof Person; // true
* martin instanceof Child; // false
*
* var ville = new Child('Ville');
* ville.greet(); // Hello, my name is Ville
* ville instanceof Person; // true
* ville instanceof Child; // true
*/
var Class = (function () {
'use strict';
var Class = {};
// Controversial, but I like it
Object.defineProperty(Function.prototype, 'extends',
new ValueDescriptor(extends_)
);
// ... or the hipster way
Object.defineProperty(Class, 'extends',
new ValueDescriptor(
function extendsFn(Constructor, Super) {
return extends_.call(Constructor, Super);
}
)
);
/**
* @this {Function} Constructor - The constructor function to extend from Super
* @param {Function|Object} Super - The constructor or object to extend from
* @return {Function} - Constructor
*/
function extends_(Super) {
var isSuperFn, Constructor = this;
if (!isFunction(Constructor)) {
throw new TypeError('Constructor must be a function');
}
isSuperFn = isFunction(Super);
if (!isSuperFn && !isObject(Super)) {
throw new TypeError('Super must be a function or an object');
}
//Inherit from Super
Constructor.prototype = Object.create(isSuperFn ? Super.prototype : Super);
Object.defineProperties(Constructor.prototype, {
//Rebind the `constructor` property
constructor: new ValueDescriptor(Constructor),
//Create the `super` method
super: new ValueDescriptor(function super_() {
return isSuperFn ? Super.apply(this, arguments) : undefined;
})
});
return Constructor;
}
function isFunction(value) {
return typeof value === 'function';
}
function isObject(value) {
return value && typeof value === 'object';
}
/**
* @constructor
* @param {*} value
* @param {Boolean} [enumerable=false]
* @param {Boolean} [configurable=false]
* @param {Boolean} [writable=false]
* @return {ValueDescriptor}
*/
function ValueDescriptor(value, enumerable, configurable, writable) {
this.value = value;
this.enumerable = !!enumerable;
this.configurable = !!configurable;
this.writable = !!writable;
}
return Class;
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment