A simple constructor extension function. Creates a constructor who prototypes "this" and adds the properties passed.
/*globals define, module */ | |
//jshint camelcase: false, curly:false | |
(function(root) { | |
'use strict'; | |
// __proto__ will be used if supported | |
//jshint -W103 | |
function prototype_PROTO(parent, child, methods) { | |
methods.__proto__ = parent.prototype; | |
child.prototype = methods; | |
} | |
function prototype_ECMA5(parent, child, methods) { | |
child.prototype = Object.create(parent.prototype); | |
Object.keys(methods).forEach(function(name) { | |
Object.defineProperty(child, name, Object.getOwnPropertyDescriptor(methods, name)); | |
}); | |
} | |
function prototype_DEFAULT(parent, child, methods) { | |
function Intermediate() { } | |
Intermediate.prototype = parent.prototype; | |
child.prototype = new Intermediate(); | |
for (var prop in methods) | |
if (methods.hasOwnProperty(prop)) | |
child.prototype[prop] = methods[prop]; | |
} | |
var prototype = {}.__proto__ ? prototype_PROTO : Object.create ? prototype_ECMA5 : prototype_DEFAULT; | |
function extend(config) { | |
config = config || {}; | |
// No strict vilation, extend should be a method of a object | |
//jshint -W040 | |
var parent = this; | |
var clazz = config.hasOwnProperty('constructor') ? | |
config.constructor : | |
function() { parent.apply(this, arguments); }; | |
prototype(parent, clazz, config || {}); | |
clazz.prototype.constructor = clazz; | |
clazz.extend = extend; | |
return clazz; | |
} | |
if (typeof define !== 'undefined' && define.amd) | |
define(function() { return extend }); | |
else if (typeof module !== 'undefined') | |
module.exports = extend; | |
else | |
root.extend = extend; | |
})(this); |
// | |
// Native constructor extension | |
// | |
var BasicType = extend.call(Object); | |
var MyOwnError = extend.call(Error, { | |
myOwnMethod: function() { | |
return 'Keep calm and debug --[' + this.message + ']--'; | |
} | |
}); | |
// | |
// Inheriting | |
// | |
var OtherError = MyOwnError.extend(); | |
console.log(MyOwnError === OtherError); | |
// > false | |
var SubType = BasicType.extend({ | |
constructor: function() { | |
BasicType.call(this); | |
console.log('constructing...'); | |
}, | |
a: 'hello world' | |
}); | |
var sample = new SubType(); | |
// > constructing... | |
console.log(sample.a); | |
// > hello world | |
console.log(sample instanceof SubType); | |
// > true | |
console.log(sample instanceof BasicType); | |
// > true | |
console.log(sample instanceof MyOwnError); | |
// > false | |
console.log(sample.constructor === SubType); | |
// > true | |
// | |
// ECMAScript5 | |
// | |
// Usually other extend functions (like underscore) will invoke the getter when .extend() is invoked. | |
var TypeWithGetter = BasicType.extend({ | |
get lol() { | |
console.log('Getting lol'); | |
return 'trololo'; | |
} | |
}); | |
var otherSample = new TypeWithGetter(); | |
console.log(otherSample.lol); | |
// > Getting lol | |
// > trololo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment