-
-
Save bennybennet/4593122 to your computer and use it in GitHub Desktop.
/* Simple JavaScript Inheritance | |
* First draft! | |
* @author Benny Bennet Jürgens (http://ben.nyben.net) | |
* CC-by-sa 3.0 - please provide my name and url | |
*/ | |
;(function() { | |
"use strict"; | |
this.BBClass = function(ctor, proto) { | |
ctor.prototype = proto || {}; | |
ctor.prototype.constructor = ctor; | |
ctor.extends = function(parent) { | |
function ChildBB() { | |
parent.prototype.constructor.apply(this, arguments); | |
ctor.apply(this, arguments); | |
}; | |
ChildBB.prototype = ( typeof Object.create !== 'function') ? | |
(function(parent) { | |
function F() {}; | |
F.prototype = parent.prototype; | |
var prototype = new F(); | |
prototype.constructor = ChildBB; | |
return prototype; | |
})(parent) | |
: Object.create(parent.prototype, { constructor: { value: ChildBB, enumerable: false }}); | |
return ChildBB; | |
} | |
return ctor; | |
} | |
}).call(this); | |
var Person = BBClass(function(isDancing) { | |
console.log("person"); | |
this.dancing = isDancing; | |
}); | |
Person.prototype.dance = function() { | |
return this.dancing; | |
}; | |
var Ninja = BBClass(function(isDancing) { | |
console.log("ninja"); | |
}).extends(Person); | |
Ninja.prototype.swingSword = function() { | |
return true; | |
}; | |
Ninja.prototype.arraytest = [1,2,3,4]; | |
var p = new Person(true); | |
var n = new Ninja(false); | |
Person.prototype.test2 = function() { console.log("test2 bestanden"); }; | |
console.log(n.arraytest); | |
console.log(p.dance()); | |
console.log(n.dance()); | |
console.log(n.swingSword()) | |
p.test2(); | |
n.test2(); | |
console.log("inherit ok?") | |
console.log( p instanceof Object); | |
console.log( p instanceof Person); | |
console.log( p instanceof Person && p instanceof Object && n instanceof Ninja && n instanceof Person && n instanceof Object); | |
=> person | |
=> person | |
=> ninja | |
=> [1,2,3,4] | |
=> true | |
=> false | |
=> true | |
=> test2 bestanden | |
=> test2 bestanden | |
=> inherit ok? | |
=> true | |
=> true | |
=> true |
Spent some more hours working on this. Does it realy make sense to go on with this?
After reading this http://javascript.crockford.com/prototypal.html and http://javascript.crockford.com/inheritance.html and especialy the paragraph
"I have been writing JavaScript for 8 years now, and I have never once found need to use an uber function. The super idea is fairly important in the classical pattern, but it appears to be unnecessary in the prototypal and functional patterns. I now see my early attempts to support the classical model in JavaScript as a mistake." (Douglas Crockford)
I came up with the idea you can see in revision 8. For now i skipped the whole super-thing, instead the child-constructor is calling the parent-constructor first and then himself (this is based on super() Java).
The performance so far is outstanding, even though i'm using Object.create. As you can see here http://jsperf.com/goog-inherit-vs-simple-inherit/2 it's a massive 100% faster in object creation and round about 30% faster for the object definition compared to the champion goog.inherit.
I'm not a JavaScript Expert which leads me to an uncomfortable situation: I'm not quite sure if i didn't make a mistake.
Improved performance of object definition and addes mixins (aka jQuery.extend - WIP). Latest performance measures: http://jsperf.com/goog-inherit-vs-simple-inherit/6
Because we don't want to execute the construtor of the base class, John Resig had a boolean in the constructor to check wether the init should be executed or not. I replaced this in the first or second revision of this gist with a surrogate-pattern, which i found in the backbonejs source. As far as i can see, this wouldn't improve the performance, but in my opinion the constructor is more clean. I tried to play with "proto" in the third or fourth revision in hope to gain some performance due to the lack of having a temp object.
Unfortunately this isn't supported by IE and not recommended to use by MDN either, so i found myself googleing more. I found this "Object.create" thingy in the MDN which seems to fit my needs. Later i found the following article explaining "Object.create" quite well: http://dailyjs.com/2012/06/04/js101-object-create/
Tested around on jsPerf quite a while http://jsperf.com/goog-inherit-vs-simple-inherit. Finally understood the way Johns extend-function does his job. "Object.create" seems 33% slower than "new" on defining the Object, around 5% faster on creating these Objects though. The most performance loss is on
which tests if the function has a "_super" call inside. Depending on
"fnTest.test()" is always true, if the browser don't support function decompilation (so function.toString()). If we would simply remove the "fnTest.test()" to gain performance, every function would be:
Whats the drawback here? Do we have another possibility to handle "_super" calls?