Skip to content

Instantly share code, notes, and snippets.

@samoshkin
Created December 27, 2012 01:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samoshkin/4384527 to your computer and use it in GitHub Desktop.
Save samoshkin/4384527 to your computer and use it in GitHub Desktop.
Prototype as class in Javascript.
// type declaration
var A = makeType({
init: function(x, y){
this.x = x;
this.y = y;
},
hello: function(){
console.log(this.x, this.y)
}
});
// B is subclass of A
var B = makeType(A, {
init: function(x, y, z){
Object.getPrototypeOf(B).init.call(this, x, y);
this.z = z;
},
hello: function(){
Object.getPrototypeOf(B).hello.call(this);
console.log("hello from b", this.z);
},
run: function(){
console.log("running", this.z)
}
});
function makeType(){
var base, declaration;
if(typeof arguments[1] !== "undefined"){
base = arguments[0];
declaration = arguments[1];
} else {
declaration = arguments[0];
}
var proto = Object.create(base || Object.prototype);
Object.getOwnPropertyNames(declaration).forEach(function(propName){
proto[propName] = declaration[propName];
});
proto.init.prototype = proto;
return proto;
}
// usage
var assert = require("assert");
// Use ECMAScript5 Object.create, then init.
// Too long for just object creation.
var a1 = Object.create(A);
a1.init(1, 2);
assert.ok(A.isPrototypeOf(a1));
a1.hello();
// the same using new. Looks odd, but could be read in this way
// create new instance of class A, and immediately init
var a2 = new A.init(1, 2);
assert.ok(A.isPrototypeOf(a2));
assert.equal(A.init.prototype, A);
// check both share same type referring to the same prototype
assert.equal(Object.getPrototypeOf(a1), Object.getPrototypeOf(a2));
// If new is omit, global object will not suffer.
// Properties will be declared on "A" prototype object(class).
var a3 = A.init(1, 2);
assert.ok(a3 === undefined);
// check B which is a subclass of A
var b1 = new B.init(1, 2, 3);
assert.ok(B.isPrototypeOf(b1));
assert.ok(A.isPrototypeOf(b1));
assert.equal(B.init.prototype, B);
b1.hello();
/*
Points for improvement:
- Ugly creation syntax
- "instanceof" operator does not work, use Object.isPrototypeOf instead
- make "Type" to be on top of prototype chain: b1 --> B --> A --> Type
Now is as follows: b1 --> B --> A --> Object.prototype
- Use property descriptors when copying properties on prototype.
This way we will not lose [[Enumerable]], [[Configurable]], [[Writeable]] attributes.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment