インスタンスごとに保護されたプロパティが必要ですか? つまりObjectA
、ObjectB
、 などによって作成されたインスタンスのプロパティですが、ライブラリ内のコードからのみアクセスでき、ライブラリ外のコードからはアクセスできないものですか?
現在、JavaScript ではこれを適切に行うことはできませんが、次のバージョンではプライベート ネーム オブジェクトを使用して行うことができます。(ただし、ES5 で現在実行できる同様のことについては、以下の「ほぼ実行中」を参照してください。)
次のように、インスタンスごとのプロパティでLib
はなく、内のすべてのコードで共有されるデータを簡単に作成できます。
window.Lib = (function()
{
var sharedData;
// ...
})();
そこに定義されているすべての関数 ( yourObjectA
など) は、その 1 つのsharedData
変数にアクセスでき、外部からは完全にアクセスできません。しかし、それはインスタンスごとではなくObjectA
、ObjectB
、 などによって作成された各オブジェクトは独自のコピーを取得しません。
ほとんどやってる
コードがES5を使用する環境で実行される場合 (つまり、「モダン」に IE8 以前が含まれない最新のブラウザー) 、. これは、プライベートな名前オブジェクトが ES.next でどのように機能するかに似ていますが、完全にプライベートではありません:Object.defineProperty
実例| ソース
window.Lib = (function() {
// Get a random name for our "c" property
var c = "__c" + Math.round(Math.random() * 1000000);
// Return our library functions
return {
ObjectA: function() {
// Create an object with a couple of public proprties:
var obj = {
pub1: "I'm a public property",
pub2: "So am I"
};
// Add our obscured "c" property to it, make sure it's
// non-enumerable (doesn't show up in for-in loops)
Object.defineProperty(obj, c, {
enumerable: false, // false is actually the default value, just emphasizing
writable: true,
value: "I'm an obscured property"
});
// Return it
return obj;
},
ObjectB: function(){ /* ... */ },
assess: function(obj) {
// Here, we access the property using the `c` variable, which
// contains the property name. In JavaScript, you can access
// properties either using dotted notation and a literal
// (`foo.propName`), or using bracketed notation and a string
// (`foo["propName"]`). Here we're using bracketed notation,
// and our `c` string, which has the actual property name.
display( obj[c] );
},
alter: function(obj, value) {
// Similarly, we can change the value with code that has
// access to the `c` variable
obj[c] = value;
}
};
})();
そして、次のように使用します。
// Create our object
var o = Lib.ObjectA();
// Play with it
display("pub1: " + o.pub1); // displays "pub1: I'm a public property"
display("c: " + o.c); // displays "c: undefined" since `o` has no property called `c`
Lib.assess(o); // displays "I'm an obscured property"
// Note that our obscured property doesn't show up in for-in loops or Object.keys:
var propName, propNames = [];
for (propName in o) {
propNames.push(propName);
}
display("propNames: " + propNames.join(","));
display("Object.keys: " + Object.keys(o).join(","));
// Our Lib code can modify the property
Lib.alter(o, "Updated obscured property");
Lib.assess(o);
によって返されるオブジェクトにLib.ObjectA
は、ロードされるたびに名前が変わるプロパティがあり、Lib
列挙できません (for-in
ループには表示されません)。それを理解する唯一の方法は、その名前を知ることです (これも、Lib
ページが読み込まれるたびに、作成されるたびに変わります)。内部のコードは、すべてのコードで共有される変数にあるLib
ため、プロパティ名が何であるかを認識しています。括弧付き表記と文字列を使用してプロパティにアクセスできるため、 を使用してプロパティにアクセスできます。c
Lib
instance[c]
これらがかなりよく隠されていることがわかります。外部のコードLib
は、オブジェクト内のプロパティを列挙するときに隠蔽されたプロパティを認識せず、割り当てた半ランダムな名前がわからないため、プロパティを見つけることができません。もちろん、デバッガーを使用して検査することで見つけることができますが、デバッガーは多くのことを行うことができます。
実際、これは ES.next でプライベート プロパティがどのように機能するかを示しています。ただしc
、これは文字列ではなく、プライベートな名前オブジェクトになります。