Skip to content

Instantly share code, notes, and snippets.

@Kambfhase
Forked from 140bytes/LICENSE.txt
Created June 5, 2011 11:59
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kambfhase/1008904 to your computer and use it in GitHub Desktop.
Save Kambfhase/1008904 to your computer and use it in GitHub Desktop.
class inheritance for real

class inheritance the way it should have been in JavaScript.

A small sketchup of how the resulting object structure will look up: http://www.abload.de/image.php?img=inhnc45.png

Usage:

 f(p,s,i) // returns the newly created class
 p: // the parent class
 s: // a property descriptor map for the static members
 i: // a property descriptor map for the instance members

 all of p,s,i are optional.

 to create a new instance of the newly created klass do:
 klass=f(p,s,i)
 Object.create(klass.prototype) // new instance

 to check if an object is an instance of klass do
 klass.isPrototypeOf( obj)

 for more examples see the unit tests.
function(p,s,i){ // parent, static, instance in that order
s = Object.create( p||{}, s); // create the new classes static object
return(
s.prototype = Object.create( // create the new instance object
p&& p.prototype ||{}, i // attach that to the statics prototype method
)
).constructor = s // make the static the instances constructor
}
function(p,s,i){s=Object.create(p||{},s);return(s.prototype=Object.create(p&&p.prototype||{},i)).constructor=s}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Kambfhase
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "class inheritance",
"description": "class inheritance the way it should have been in JavaScript.",
"keywords": [
"classes",
"inheritance"
]
}
<!doctype html>
<html>
<head>
<link href="qunit.css" rel="Stylesheet" type="text/css"/>
<title>Unit Tests</title>
</head>
<body>
<h1 id="qunit-header">Din - Unit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup, will be hidden</div>
<script src="qunit.js"></script>
<script>
var Class={
create2:
function f(p,s,i){s=Object.create(p||{},s);return (s.prototype=Object.create((p&&p.prototype)||{},i)).constructor=s}
,
create: function(o){
var k = this.create2(o.parent,o.static,o.instance);
if( !k.create)
k.create = function(){return Object.create(this.prototype)};
if( !k.is)
k.is = function( obj){ return this.prototype.isPrototypeOf(obj);};
return k;
}
}
</script>
<script>
module("Basic basics");
test("Basic setup", function(){
expect(3);
ok( Class,"Class exists");
ok( Class.create,"Class.create exists");
equals( typeof Class.create, "function", "Class.create is a function");
});
module("simple class");
var Klass = Class.create({
// no parent
"static":{
method: {
value: function(){
return 2;
}
},
self: {
value: function(){
return this;
}
}
},
instance: {
method: {
value: function(){
return 2;
}
},
prop: {
value: "foo",
enumerable: true,
writable:true,
configurable:true
},
accessor: {
get: function(){
return 1;
},
enumerable: true
},
self: {
value: function(){
return this;
}
}
}
}),k=Klass.create();
test("simple basics", function(){
expect(7);
ok( Klass,"Klass exists");
ok( Klass.prototype,"Klass.prototype exists");
ok( Klass.prototype.constructor== Klass, "Klass is its instances Constructor");
equals( typeof Klass.create, "function", "Klass.create is a function");
equals( typeof Klass.is, "function", "Klass.is is a function");
ok( Klass.create(), "Klass.create returns something");
//ok( k instanceof Klass, "k is an instance of Klass"); //?
ok( Klass.is( k),"k is an instance of Klass");
});
test("correct instances",function(){
expect(7);
equals( typeof k.method, "function","k.method should be a function");
equals( k.method(), 2, "yay!");
equals( typeof k.prop, "string","k.prop is a string");
equals( k.prop, "foo");
equals( typeof k.accessor, "number","getter returns a value");
equals( k.accessor, 1,"accessor returns gettet value");
ok( k.self() == k,"correct <this>");
});
test("correct descriptors",function(){
var p = Klass.prototype, d;
expect(13);
ok( p.hasOwnProperty("method"),"method should be on the prototype");
d=Object.getOwnPropertyDescriptor(p, "method");
equals(d.enumerable, false, "method is not enumerable");
equals(d.writable, false, "method is not writable");
equals(d.configurable, false, "method is not configurable");
ok( p.hasOwnProperty("prop"),"prop should be on the prototype");
d=Object.getOwnPropertyDescriptor(p, "prop");
equals(d.value, "foo", "prop is 'foo'");
equals(d.enumerable, true, "prop is enumerable");
equals(d.writable, true, "prop is writable");
equals(d.configurable, true, "prop is configurable");
ok( p.hasOwnProperty("accessor"),"accessor should be on the prototype");
d=Object.getOwnPropertyDescriptor(p, "accessor");
ok(d.get, "getter is defined");
equals(d.enumerable, true, "accessor is enumerable");
equals(d.configurable, false, "accessor is not configurable");
});
test("Staticness",function(){
expect(4);
ok( Klass.method, "static method exists");
ok( Klass.method != k.method, "static and instance method differ");
equals( Klass.method(), 2, "static returns correct result");
ok( Klass.self() == Klass, "correct <this>");
});
module("inheritance");
var A = Class.create({
instance : {
foo: {
value: function(){
return "A foo";
}
}
}
}),
B = Class.create({
parent: A,
"static":{
bar: {
value: function(){
return "b bar";
}
}
}
}),
C = Class.create({
parent: B,
instance: {
foo: {
value: function(){
return "C "+A.prototype.foo.call(this);
}
}
}
}),a=A.create(),b=B.create(),c=C.create();
test("static inheritance", function(){
expect(4);
ok( !!B.bar(),"B has a static bar method");
ok( !!C.bar(),"C has a static bar method");
equals( B.bar, C.bar,"C inherits static method from B!");
equals( B.bar(), C.bar(), "same!");
});
test("creation", function(){
expect(9);
equals( A.is( a), true, "a is an instance of A");
equals( A.is( b), true, "b is an instance of A");
equals( A.is( c), true, "c is an instance of A");
equals( B.is( a), false, "a is not an instance of B");
equals( B.is( b), true, "b is an instance of B");
equals( B.is( c), true, "c is an instance of B");
equals( C.is( a), false, "a is not an instance of C");
equals( C.is( b), false, "b is not an instance of C");
equals( C.is( c), true, "c is an instance of C");
});
test("instance inheritance",function(){
expect(4);
equals( a.foo(), "A foo", "a foo is a foo :|");
equals( b.foo(), "A foo", "b.foo is also a foo :|");
equals( b.foo, a.foo, "same foo methods");
equals( c.foo(), "C A foo","c foo is c a foo");
});
</script>
</body>
</html>
@atesgoral
Copy link

You could probably alias Object.create and prototype to shave off some bytes.

@Kambfhase
Copy link
Author

oh, yeah, will do!

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