Bondye が提供するリンクによって提供されるモジュール パターンは、プライベートインスタンスプロパティを保持しないことに注意してください。関数はインスタンスごとに変更されないため、関数のプロパティには最適ですが、次のコードが示すように、値のプロパティに対しては少し予測できない動作をします。
var module = (function () {
// private variables and functions
var foo = 'bar';
// constructor
var module = function (name) {
// instance variables
this.name=name;
};
// prototype
module.prototype = {
constructor: module,
something: function () {
// notice we're not using this.foo
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
};
// return module
return module;
})();
var m1 = new module("m1");
var m2 = new module("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: new value
コードの最後の行でわかるように、m1 と m2 の両方のインスタンスが foo という名前のプライベート変数を共有しています (すべてのインスタンスが同じ値を指します)。
Bondye が投稿した他のリンクからわかることは、JavaScript でプライベート性をシミュレートするのは難しく、名前付け規則を使用してプロパティがプライベートであることを示すことを検討できるということです。Google クロージャ コンパイラなどを使用して、JS コードに注釈を付けてプライベートを示すことができます。ただし、クロージャー コンパイラーの使用には独自の欠点があります (Closure Compiler と互換性があり、コードが高度なモードでコンパイルされる特定の形式である必要がある場合を除き、使用されるライブラリはコンパイルできません)。
もう 1 つのオプションは、プロトタイプを完全に破棄し (少なくともすべてプライベート プロパティを使用して)、コンストラクター関数の本体にすべてを配置する (またはオブジェクトを返す関数を使用する) ことです。
// function returning an object
function makeObj(name){
// private vars:
var foo = "bar";
return {
name:name,
something:function(){
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
}
}
var m1=makeObj("m1");
var m2=makeObj("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: bar
// constructor with everything in the constructor's body:
function Obj(name){
// private vars:
var foo = "bar";
this.name=name;
this.something=function(){
console.log("foo in "+this.name+" is:",foo);
foo="new value";
}
}
Obj.prototype.someOtherFunction=function(){
// anything here can't access the "private" variables
}
var m1=new Obj("m1");
var m2=new Obj("m2");
m1.something();// foo in m1 is: bar
m1.something();// foo in m1 is: new value
m2.something();// foo in m2 is: bar
プライベート インスタンス値を使用する際に発生する可能性のあるもう 1 つの問題は、それらがインスタンス内でのみアクセスできることです。オブジェクトのクローンを作成し、オブジェクトにクローン関数を定義して新しいインスタンスを作成する場合は、パブリック アクセサー関数を記述してプライベート値を設定する必要があります。これは、 Java プライベート フィールドのように値を直接設定できないためです。
コンストラクター関数の使用に関する詳細情報:プロトタイプの継承 - 書き上げ