Created
May 14, 2011 18:02
-
-
Save teramako/972456 to your computer and use it in GitHub Desktop.
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
// =================================== | |
// Example | |
// =================================== | |
/** | |
* Point | |
* @class | |
* @augments Class | |
* @param {Number} x x-axis | |
* @param {Number} y y-axis | |
*/ | |
const Point = Class("Point", /** @lends Point# */ { | |
/** @constructs */ | |
init: function Point (x, y) { | |
if (x) this.x = x; | |
if (y) this.y = y; | |
}, | |
/** | |
* x-axis | |
* @type Number | |
*/ | |
x: 0, | |
/** | |
* y-axis | |
* @type Number | |
*/ | |
y: 0, | |
}); | |
/** | |
* Rectangle | |
* @class | |
* @augments Point | |
* @param {Number} x | |
* @param {Number} y | |
* @param {Number} width | |
* @param {Number} height | |
*/ | |
const Rectangle = Class("Rect", Point, /** @lends Rectangle# */ { | |
/** @constructs */ | |
init: function Rectangle (x, y, width, height) { | |
if (width) this.width = width; | |
if (height) this.height = height; | |
arguments.callee.super.call(this, x, y); | |
}, | |
getDimension: function Rect_getDimension () { | |
return this.width * this.height; | |
}, | |
/** | |
* width of the rect | |
* @type Number | |
*/ | |
width: 0, | |
/** | |
* height of the rect | |
* @type Number | |
*/ | |
height: 0, | |
}); | |
/** | |
* Square | |
* @class | |
* @augments Rectangle | |
* @param {Number} x | |
* @param {Number} y | |
* @param {Number} length | |
*/ | |
const Square = Class("Square", Rectangle, /** @lends Square */ { | |
/** @constructs */ | |
init: function Square (x, y, length) { | |
arguments.callee.super.call(this, x, y, length, length); | |
}, | |
/** | |
* @name Square#length | |
* @type Number | |
*/ | |
get length () { | |
return this.width; | |
}, | |
set length (val) { | |
return this.width = this.height = val; | |
} | |
}); | |
var p = new Point(10,10); // Point instance; | |
p instanceof Point; // true | |
p instanceof Class // true | |
var rect = Rectangle(10, 15, 20, 30); // can omit `new' operator | |
rect instanceof Rect; // true | |
rect instanceof Point; // true | |
rect instanceof Class; // true | |
rect.x; // 10 | |
rect.y; // 15 | |
rect.width; // 20 | |
rect.height; // 30 | |
var sq = Square(20, 10, 30); | |
sq.getDimension(); // 900 (30 * 30), | |
// vim: sw=2 ts=2 et: |
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
/** | |
* @fileoverview Create Function like Class | |
* @author teramako teramako.at.gmail.com | |
* @version 0.1 | |
* @license MIT | |
* @requires ECMASCript 5th and object.__proto__ property | |
*/ | |
/** | |
* Create Function constructor | |
* @constructor | |
* @augments Object | |
* @param {String} [name] class name | |
* @param {Function} [base] base class | |
* @param {Object} proto | |
* @return {Function} | |
*/ | |
function Class (name, base, proto) { | |
var args = Array.prototype.slice.call(arguments); | |
if (typeof args[0] == "string") | |
var name = args.shift(); | |
var superClass = Class; | |
if (typeof args[0] == "function") | |
superClass = args.shift(); | |
proto = args[0]; | |
if (!name) | |
name = proto.__CLASS_NAME__ || superClass.__CLASS_NAME__ || "Anonymous"; | |
proto.__proto__ = superClass.prototype; | |
Class.setSuper(proto, superClass.prototype); | |
Object.defineProperty(proto, "__CLASS_NAME__", { value: name }); | |
var constructor = function () { | |
var o = Object.create(proto, { constructor: { value: constructor }}); | |
var res = o.init.apply(o, arguments); | |
return res != undefined ? res : o; | |
}; | |
constructor.prototype = proto; | |
var bound = constructor.bind(null); | |
bound.prototype = proto; | |
bound.__proto__ = Class; | |
return bound; | |
} | |
Object.defineProperties(Class, { | |
/** | |
* Show the first class name. | |
* @name Class.toString | |
* @function | |
* @return {String} | |
*/ | |
toString: { | |
value: function () { return "[class " + this.prototype.__CLASS_NAME__ + "]"; }, | |
}, | |
/** | |
* set "super" property is references the same name property in super | |
* to functions and gettter/setter properties in proto | |
* @name Class.setSuper | |
* @function | |
* @constant | |
* @param {Object} proto | |
* @param {Object} super | |
*/ | |
setSuper: { | |
value: function (proto, super) { | |
var keys = Object.getOwnPropertyNames(proto); | |
out: | |
for (var i = 0, len = keys.length; i < len; ++i) { | |
var key = keys[i]; | |
if (!(key in super)) | |
continue; | |
var desc = Object.getOwnPropertyDescriptor(proto, key); | |
if ("get" in desc) { | |
var p = super; | |
while (p !== null) { | |
if (Object.prototype.hasOwnProperty(p, key)) { | |
Object.defineProperty(proto[key], "super", desc); | |
continue out; | |
} | |
p = Object.getPrototypeOf(p); | |
} | |
} else if (typeof proto[key] == "function") { | |
Object.defineProperty(proto[key], "super", { value: super[key] }); | |
} | |
} | |
}, | |
}, | |
/** | |
* marge properties of the second or later arguments | |
* to the first arguments | |
* @function | |
* @name Class.update | |
*/ | |
update: { | |
value: function () { | |
var args = Array.prototype.slice.call(arguments); | |
var base = args.shift(); | |
for (var i = 0; i < args.length; ++i) { | |
var o = args[i]; | |
var keys = Object.getOwnPropertyNames(o); | |
for (var k = 0, len = keys.length; k < len; ++k) { | |
var key = keys[i]; | |
Object.defineProperty(base, key, Object.getOwnPropertyDescriptor(o, key)); | |
} | |
} | |
}, | |
}, | |
}); | |
Class.prototype = Object.create({}, { | |
/** | |
* @memberof Class.prototype | |
* @type {String} | |
* @private | |
*/ | |
__CLASS_NAME__: { value: "Class", }, | |
/** | |
* do nothing | |
* @methodof Class.prototype | |
* @constructs | |
*/ | |
init: { | |
value: function Class_init () {}, | |
}, | |
/** | |
* Show the first class name of the instance. | |
* @methodof Class.prototype | |
* @return {String} | |
*/ | |
toString: { | |
value: function Class_toString () { return "[instance " + this.__CLASS_NAME__ + "]"; }, | |
}, | |
}); | |
// vim: sw=2 ts=2 et: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment