内部変数 (フィールド) 定義 ~ JavaScript によるオブジェクト指向プログラミング
クラスの内部変数ということは、それぞれのオブジェクトの状態とも言い換えられます。
今回の例で取り上げている Person (人) クラスの場合、例えば名前や年齢が内部データになります。
内部変数は prototype にではなく、this に設定します。this に内部変数を設定することにより、 その変数がオブジェクトワイドの変数として定義されます。prototype に指定すると、 クラスワイドになってしまい、オブジェクト間で同じ値になってしまうのです。
さっそく、サンプルコードを見てみましょう。
var Person = function ( n ) { this.name = n; } Person.prototype.say_hello = function() { alert( this.name ); } var p1 = new Person('Ichiro Suzuki'); var p2 = new Person('Hanako Yamada'); p1.say_hello(); // 'Ichiro Suzuki' が表示される p2.say_hello(); // 'Hanako Yamada' が表示される
ここでは、コンストラクタ Person で引数に n を受け取り、それを this.name に代入しています。
say_hello メソッドでは、this を経由して、name にアクセスしてそれを alert で表示しています。
このように定義しておくと、p1, p2 のようにそれぞれのインスタンスで、異なる name 値を持つことが可能になります。
内部変数の保護
上で紹介した方法は new を用いており、C++ 等になれた人にはなじみのある構文でわかりやすい という利点があるものの、name が保護されていないという問題があります。
例えば上記の例では、以下のように name に直接アクセスし書き換えることが可能になります。
var Person = function ( n ) { this.name = n; } Person.prototype.say_hello = function() { alert( this.name ); } var p1 = new Person('Ichiro Suzuki'); p1.say_hello(); // 'Ichiro Suzuki' が表示される p1.name = 'Hanako Yamada'; p1.say_hello(); // 'Hanako Yamada' が表示される
オブジェクト指向では、データのカプセル化は非常に重要です。
そこで、プライベート変数とするために次のように書きます。
var person = function (n) { var name = n; return { say_hello: function() { alert( name ); } }; }; var p1 = person('Ichiro Suzuki'); p1.say_hello();
このようにすると、変数 name にはアクセスすることが出来ません。 例えば以下のように name に 'Hanako Yamada' を代入しようと試みても、 内部変数 name を書き換えることは出来ません。
var person = function (n) {
var name = n;
return {
say_hello: function() {
alert( name );
}
};
};
var p1 = person('Ichiro Suzuki');
p1.say_hello(); // 'Ichiro Suzuki' が表示される
p1.name = 'Hanako Yamada';
p1.say_hello(); // 'Ichiro Suzuki' が表示される
このコードを理解するにはクロージャ (closure) を理解しなければなりません。
それでは次にこのコードを用いて、クロージャについて説明します。