2013年11月18日月曜日

連載:ちょっとディープなXPages 第2-8回~JavaScriptをもっと知ろう

青太字文字部分、加筆しました。

みなさん!XPages開発していますか!?

前回はコンストラクタ関数について説明しましたが、前回の方法ではnewを呼び出す度にfunctionが生成されるので、非効率です。

var User = function(name){
    this.name = name; //プロパティ
    //下記のfunctionがnewが呼び出される度に生成されるの非効率
    this.sayHello = function(){
        return this.name + 'さん、こんにちは!';
    } //メソッド
}

prototype

この問題を解決するにはprototypeを使用するのが簡単な解決方法です。

var User = function(name){
    if(!!name){
        this.name = name;
    }
}
User.prototype = {
    name : '', //プロパティ
    sayHello : function(){
        return this.name + 'さん、こんにちは!';
    } //メソッド
}
//オブジェクト作成
var kenji = new User('Kenji');
print(kenji.name); // 'Kenji'
print(kenji.sayHello()); // Kenjiさん、こんにちは!

prototypeはすべてのfunctionオブジェクトに存在する特殊なメンバーで、通常は上記のようにオブジェクトを保持します。

上記のように、Userコンストラクタ関数ではsyaHelloメソッドはないにもかかわらず、呼び出せています。

それは、「オブジェクトに存在しないメンバを呼ばれたときは、自身のprototypeオブジェクトを参照し、そこにあればそれを呼び出す」というjavascript特有の言語仕様があるためです。

さらに、prototypeオブジェクトは new で作成されたオブジェクトに関係なく1つのオブジェクトなため、new でオブジェクトをいくつ作成しても、参照される sayHello はメモリ的にも同じものとなり、効率的です。

また、上記の例では new の引数に null または undefinde 以外が渡された場合は、name プロパティがセットされます。この場合は、kenji にはnameプロパティが存在するので、prototypeのnameは採用されず、Userのコンストラクタ関数で割り当てられたkenji の name プロパティが採用されます。

prototypeチェーン

さて、prototypeはオブジェクトですが、このオブジェクトにprototypeが定義されている場合は、どのような動作になるでしょうか?下記の例を見てみます。

var p1 = function(){
}
p1.prototype = {
    name : '1st!'
}
var p2 = function(){
}
p2.prototype = (function(){
    var obj = new p1();
    obj.old = 20;
    return obj;
})();
var c3 = new p2();

//c3は、name と old にアクセスできる
print(c3.name); // '1st!'
print(c3.old); // 20
    

c3 は p2 コンストラクタ関数から生成されます。p2 コンストラクタ関数のprototype は p1 コンストラクタ関数から生成したオブジェクトにメンバーを追加したものになります。p1 コンストラクタ関数の prototype は name プロパティを持ちます。

そうした場合、c3は p2 の prototype にも p1の prototype にもアクセスされます。

イメージ

これを利用して、クラスの継承的な実装が可能になりますが、これに関してはもう少し整理して別の機会に説明したいと思います。

海老原 賢次(EBIHARA Kenji)

リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)

鹿児島ソリューション部(Kagoshima Department)

 

0 件のコメント:

コメントを投稿