参照型(※)は初期値にしない
JavaScriptでクラス(ライクなオブジェクト)を作る時、インスタンスプロパティに配列やハッシュ(のようなオブジェクト)を設計することはよくやると思います。
そんな時注意しなければならないのが、参照型(※)の値は初期値として設定しないということ。
CoffeeScriptの場合
# ダメなパターン
class Foo
array: []
object: {}
foo = new Foo
foo2 = new Foo
foo.array.push 'オラァ'
foo.object.a = '無駄ァ'
# foo に設定したはずが foo2 にも影響する
console.log foo2.array[0] # => 'オラァ'
console.log foo2.object.a # => '無駄ァ'
# 大丈夫なパターン
class Bar
array: null # 初期値はnull
object: null # 初期値はnull
constructor: ->
@array = [] # 本当に利用したい初期値を設定
@object = {} # 本当に利用したい初期値を設定
bar = new Bar
bar2 = new Bar
bar.array.push 'オラァ'
bar.object.a = '無駄ァ'
# 影響しない
console.log bar2.array[0] # => undefined
console.log bar2.object.a # => undefined
JavaScriptではつまりこういうこと
// ダメなパターン
function Foo () {}
Foo.prototype.array = [];
Foo.prototype.object = {};
// 大丈夫なパターン
function Bar () {
this.array = [];
this.object = {};
}
Bar.prototype.array = null;
Bar.prototype.object = null;
なぜこうなるの?
それは君「プロトタイプチェーン」だよ!
プロトタイプチェーンとは
ここで説明するには奥が深すぎるので、説明しません!以下など参照にしてください。
や...やっと理解できた!JavaScriptのプロトタイプチェーン
実はnullと設定する必要はないのでは?
基本的にそのとおりです。
ただ、Coffeeの場合など"明示的"にプロパティの宣言をしたいので先のような記述にしています。
コンストラクタ内で設定するというガイドラインもあっても問題ないと思います。
※参照型について
値をざっくり分類すると
基本型
- 論理値
- 数値
- 文字列
- null
- undefined
参照型
- 配列
- オブジェクト
- 関数 などなど
性質などはこれも今更ここで説明することでもないので割愛。
ちなみにオブジェクトの参照型扱いについて以下を参照してください。
誤り : JavaScript のオブジェクト型は参照型ではないというお話
詳しい説明は全くしませんでしたが、つまりそういうことなので覚えておきましょう。