タイムラインに流れてきたツイートを見て興味がわいたので頼まれてもいないのに勝手に挑戦してみる。
要件は
- シングルトンである
- privateメンバが定義できる
- prototype拡張できる
- コンストラクタ関数の中でif文で分岐してインスタンス生成拒否は美しくない
singleton.js
(function (global) {
// こいつがコンストラクタということにする
global.Hoge = Hoge;
// インスタンスを作る本当のコンストラクタはこっち
var ctor = function () { };
// prototype を共有
ctor.prototype = Hoge.prototype;
// シングルトンインスタンス
global.hoge = new ctor();
// private properties
var privateProperty = "private property";
// public members
global.hoge.publicProperty = 'public property';
global.hoge.publicMethod = publicMethod;
// constructor
function Hoge() {
throw new Error('シングルトンだから new しちゃダメよ');
};
// public methods
function publicMethod() {
console.log('public method called.');
// privateMethod.call で呼ぶのもいいかも
privateMethod();
console.log(privateProperty);
}
// private methods
function privateMethod() {
console.log('private method called.');
}
}(this));
// public プロパティにアクセス
console.log(hoge.publicProperty);
// public メソッドにアクセス
hoge.publicMethod();
// Hoge のインスタンスとして判断できる
console.log(hoge instanceof Hoge);
// new Hoge は例外
try {
var fuga = new Hoge();
} catch (ex) {
console.log(ex.message);
}
// prototype に拡張(でも hoge 自体に拡張しても問題ないのでは?)
Hoge.prototype.doSomething = function () {
console.log('extended!!');
};
// 拡張したメソッドを呼べる
hoge.doSomething();