Created
December 27, 2012 01:01
-
-
Save samoshkin/4384527 to your computer and use it in GitHub Desktop.
Prototype as class in Javascript.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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