Hatena::ブログ(Diary)

oct inaodu

 | 

2005-10-28

JavaScriptにおけるプライベートメンバ


原文:Private Members in JavaScript

Copyright 2001 Douglas Crockford. All Rights Reserved Wrrrldwide.


JavaScriptJavaScript: 世界で最も誤解されたプログラミング言語です。JavaScriptオブジェクトが、プライベートなインスタンス変数およびインスタンスメソッドを持てないため情報を隠蔽する能力が欠けていると思われることがあります。しかし、これは誤解です。JavaScriptオブジェクトは、プライベートメンバを持つことができます。その方法は以下です。

オブジェクト

JavaScriptオブジェクトを基礎としています。配列オブジェクトです。関数オブジェクトです。オブジェクトオブジェクトです。それならば、オブジェクトとは何でしょう?オブジェクトは名前と値のペアの集合です。名前は文字列で、値は文字列、数値、真偽値、およびオブジェクト(配列関数を含む)です。通常、オブジェクトハッシュテーブルとして実装されるため、素早く値を取得できます。


値が関数の場合、それはメソッドと見なせます。オブジェクトのメソッドが呼び出された時、this変数オブジェクトにセットされます。メソッドはthis変数を通じてインスタンス変数アクセスできます。


オブジェクトは、コンストラクタにより生成できます。コンストラクタは、オブジェクトを初期化する関数です。コンストラクタは、他言語におけるクラスの機能を提供し、静的変数と静的メソッドを含みます。

パブリック

オブジェクトのメンバは、全てがパブリックメンバです。どんな関数からもメンバへアクセスでき、メンバを修正、削除することもできます。また、新しいメンバを追加することも可能です。新しいオブジェクトにメンバを追加するには、主に2つの方法があります。

コンストラクタでの追加

通常この方法は、パブリックインスタンス変数を初期化するのに利用されます。オブジェクトにメンバを追加するには、コンストラクタのthis変数を使います。

function Container(param) {
    this.member = param;
}

そして、新しいオブジェクトを作るコードは以下です。

var myContainer = new Container('abc');

上記により、myContainer.memberに'abc'が入りました。

プロトタイプでの追加

通常この方法は、パブリックなメソッドを追加するのに利用されます。オジェクト自身からメンバを探して見つからない場合、オブジェクトのコンストラクタのprototypeメンバからメンバが取得されます。プロトタイプのメカニズムは継承に用いられますし、またメモリの節約にも役立ちます。コンストラクタによって作られた全てのオブジェクトにメソッドを追加するには、コンストラクタのprototype関数を追加します。

Container.prototype.stamp = function (string) {
    return this.member + string;
}

そして、追加したメソッドを呼び出せます。

myContainer.stamp('def')

これは'abcdef'を返します。

プライベート

プライベートメンバはコンストラクタにより作られます。通常は、varにより定義される変数とコンストラクタの引数がプライベートメンバになります。

function Container(param) {
    this.member = param;
    var secret = 3;
    var self = this;
}

このコンストラクタは、param、 secret、 selfの3つのプライベートインスタンス変数をつくります。これらの変数オブジェクトに所属していますが、外部からアクセスすることも、オブジェクト自身のパブリックメソッドからアクセスすることもできません。プライベートインスタンス変数は、プライベートメソッドからアクセスできます。プライベートメソッドはコンストラクタの内部関数です。

function Container(param) {

    function dec() {
        if (secret > 0) {
            secret -= 1;
            return true;
        } else {
            return false;
        }
    }

    this.member = param;
    var secret = 3;
    var self = this;
}

プライベートメソッドのdecは、secretインスタンス変数をチェックし、secretがゼロより大きい場合はsecretを1減らしtrueを返します。それ以外はfalseを返します。これは、このオブジェクトの利用を3回に制限するために使うことができます。


慣例に従い、プライベートのself変数を作ります。この変数はプライベートメソッドからオブジェクト自身を参照できるようにするために使われます。これは内部関数に不正確なthisをセットする、ECMAScript言語仕様の不具合を回避するための手段です。


パブリックメソッドからプライベートメソッドを呼ぶことはできません。プライベートメソッドを活用するためには、プリビレッジドメソッドを導入する必要があります。

プリビレッジド

プリビレッジドメソッド(特権メソッド)は、プライベート変数とプライベートメソッドにアクセスできます。そしてパブリックメソッドや外部からアクセスすることもできます。プリビレッジドメソッドを削除したり置き換えたりすることはできますが、それを改竄したり、隠蔽しているものを無理に明け渡させることはできません。


プリビレッジドメソッドは、コンストラクタの内部でthisへ割り当てられます。

function Container(param) {

    function dec() {
        if (secret > 0) {
            secret -= 1;
            return true;
        } else {
            return false;
        }
    }

    this.member = param;
    var secret = 3;
    var self = this;

    this.service = function () {
        if (dec()) {
            return self.member;
        } else {
            return null;
        }
    };
}

serviceはプリビレッジドメソッドです。myContainer.service()を呼び出すと、最初に呼び出されてから3回までは'abc'を返しますが、それ以降はnullを返します。serviceは、プライベート変数secretにアクセスするプライベートメソッドdecを呼び出します。serviceを他のオブジェクトやメソッドから利用することはできますが、プライベートメンバに直接アクセスすることは許しません。

クロージャ

パブリック、プライベート、プリビレッジドのパターンが使えるのは、JavaScriptにクロージャが備わっているためです。つまり内部関数が、外部関数が終了した後でも、常に外部関数のvarで宣言された変数パラメータアクセスできるということです。これはJavaScriptの非常に力強い特性です。しかし、クロージャの有効な利用法について書かれているJavaScriptプログラミングの本は現時点では存在しませんし、大部分の本はそれに触れることさえないのです。


プライベートメンバとプリビレッジドメンバはオブジェクト作成時にのみ作ることができます。パブリックメンバはいつでも追加可能です。

パターン

パブリック

function Constructor(...) {

  this.membername = value;

}

Constructor.prototype.membername = value;

プライベート

function Constructor(...) {

  var self = this;

  var membername = value;

  function membername(...) {...}

}

メモ : functionステートメントは、

function membername(...) {...}

以下の省略形です。

var membername = function membername(...) {...};

プリビレッジド

function Constructor(...) {

  this.membername = function (...) {...};

}

Maria TurnerMaria Turner 2006/02/13 20:04 <h1><a href=”http://advertisersworld.com/buy-tamiflu-on-line/”>buy tamiflu on line</a> http://advertisersworld.com/buy-tamiflu-on-line/ [URL=http://advertisersworld.com/buy-tamiflu-on-line/]buy tamiflu on line[/URL] [URL]http://advertisersworld.com/buy-tamiflu-on-line/[/URL]</h1>

hiroshima takakihiroshima takaki 2007/02/05 19:04 Whether this great defect:--_every_ Englishman who wore a good deal of caution in getting the ship, expending all their greatest enjoyments in bygone days. http://www.qvgs.com/156/hiroshima-takaki.html <a href=”http://www.qvgs.com/156/hiroshima-takaki.html”>hiroshima takaki</a> [url]http://www.qvgs.com/156/hiroshima-takaki.html[/url]

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

 |