JavaScript プロパティ lazy build 遅延初期化 getter メソッド
JavaScript で getter メソッド経由でプロパティの値を lazy build(lazy initialization/遅延初期化)する方法について。
handlebars とかのテンプレートエンジンに渡すオブジェクトで、テンプレート側で使う場合のみ必要に応じて lazy build したかった。予め getter を作っておけば、プロパティとしてテンプレートからアクセスできる。
var seq = 0; var Foo = function () { this.seq = ++ seq; }; var Bar = function () { this.fooB = new Foo(); }; Bar.prototype = { fooA: new Foo(), // shared get fooC() { return this._fooC = this._fooC || new Foo(); // lazy build } }; var bar1 = new Bar(); var bar2 = new Bar(); var bar3 = new Bar(); console.log('bar1', bar1.fooA.seq, bar1.fooB.seq, bar1.fooC.seq); // 1 2 5 console.log('bar3', bar3.fooA.seq, bar3.fooB.seq, bar3.fooC.seq); // 1 4 6 console.log('bar2', bar2.fooA.seq, bar2.fooB.seq, bar2.fooC.seq); // 1 3 7
Foo の seq プロパティは、Foo インスタンスを生成したシリアル番号。
Bar の fooA・fooB・fooC プロパティは、いずれも Foo のインスタンスを持つ。
(prototype にインスタンスを持たせる場合)
fooA プロパティは、Bar.prototype 定義時に Foo インスタンスができていて、
全ての Bar インスタンスで共有されるので、bar1/bar2/bar3 いずれも 1 となる。
(通常のプロパティ値にインスタンスを持たせる場合)
fooB プロパティは、Bar インスタンス作成時に Foo インスタンスができるので、
Bar インスタンスの生成順から、bar1=2→bar3=4→bar2=3 という結果になる。
(プロパティ値を lazy build する場合)※今回の主旨
fooC プロパティは、fooB プロパティを呼び出した際に Foo インスタンスができるので、
fooC プロパティのアクセス順から、bar1=5→bar3=6→bar2=7 という結果になる。
実際の Foo インスタンスは _fooC というプライベート風味プロパティに置いた。
get fooC() のゲッター定義が使えない古い環境では以下を使う。
Bar.prototype.__defineGetter__('fooC', function(){ return this._foo = this._foo || new Foo(); });
(参考記事)
http://news.mynavi.jp/articles/2010/09/09/ie9-ie8-getter-setter-javascript/index.html
http://d.hatena.ne.jp/amachang/20090115/1231989477
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineGetter
CC BY-SA 3.0 の 下駄 は Haragayato さん。