私はしばらくプロトタイプ ライブラリを使用してきましたが、複数のアクセス レベル (パブリック、プライベート、および保護) があればいいのにと思うことがあります。これまでに最も近いのは次のとおりです。
SampleBase = Class.create({
/* virtual public constructor */
initialize: function(arg1, arg2)
{
// private variables
var privateVar1, privateVar2;
// private methods
var privateMethod1 = function() { }
function privateMethod2() { }
// public (non virtual) methods
this.publicNonVirtual1 = function() { return privateVar1; }
this.publicNonVirtual2 = function() { return privateVar2; }
},
// public methods (that cannot access privates)
publicVirtual1: function() { /* Cannot access privates here. */ },
publicVirtual2: function() { /* Cannot access privates here. */ }
});
これは、いくつかの理由で理想的とは言えません。
- 保護レベルなし
- プライベート メンバーにアクセスできるパブリック メンバー、またはオーバーライドできるパブリック メンバーを使用できますが、プライベート メンバーにアクセスしてオーバーライドできるパブリック メンバーは作成できません。
- オーバーライドできるパブリック メソッドはプロトタイプ化されていません。
私はいくつかの検索を行いましたが、プロトタイプの動作を変更せずに改善できることを示唆するものは何も見つかりませんでした. より興味深いリンクのいくつかを次に示します。
- プロトタイプの Class.create を使用して、プライベート/保護されたプロパティとメソッドを定義する
- JavaScript プライベート メソッド
- JavaScript のプライベート メンバー
- 再びモジュール パターンを使用して、世界に何かを明らかにします
次のようなことを行うことで、パブリック仮想メソッドが使用するアクセサーを提供できることが示唆されているのを見てきました。
Message = Class.create({
initialize: function(message)
{
var _message = message;
this.getMessage = function() { return _message; }
this.setMessage = function(value) { _message = value; }
},
printMessage: function() { console.log(this.getMessage()); },
appendToMessage: function(value) { this.setMessage(this.getMessage() + value); }
});
これは明らかに意図したとおりには機能しません。目標は、オブジェクトの外部からのメッセージへの印刷と追加のみを許可することです。仮想パブリック関数を機能させるために提供されるセッターは、メッセージの完全な制御も可能にします。次のように、仮想メソッドをシェルよりも少し多くするように変更できます。
Message = Class.create({
initialize: function(message)
{
var _message = message;
this._printMessage = function() { console.log(_message); }
this._appendToMessage = function(value) { _message += value; }
},
printMessage: function() {this._printMessage(); },
appendToMessage: function(value) { this._appendToMessage(value); }
});
この新しいバージョンでは、このクラスのパブリック アクセスが制限されていますが、やや冗長です。サブクラスで appendToMessage がオーバーライドされている場合は言うまでもなく、サードパーティが _appendToMessage を呼び出して元のメソッドにアクセスできますが、これは良くありません。
私は私を近づける非常に汚い考えを持っていますが、開けたくないワームの缶です. 後で投稿するかもしれませんが、その間に、2 つのタイプのパブリック メソッドを 1 つの有用なタイプにマージする方法や、保護されたメンバーを実装する方法について提案がある人はいますか。
編集:フィードバックの欠如(bobinceのコメントを気にしないでください)は、これ以上先に進むことができないという点で私が正しいことを意味すると思いますが、念のため少し明確にすると思います。他の言語の保護に近いものを手に入れることは不可能だと思います。限界がどこにあるのか、関係する原則についての私の理解がどれほど正確であるかを知ることにもっと興味があります。ただし、非公開メンバーが for...in ループ (または Prototypes Object.keys for..in) を使用している場合でも、自分が何をしているかを知っている人が、私のプロトタイプをいじるなどしてルールを破ることができます。やっぱりボビンスみたい「彼らは自分以外に責任を負わない」と言う
bobinceによって提起された問題についてコメントします。
実際のプライベート/保護された変数を作成したとしても、効果的なセキュリティ境界に必要な完全なカプセル化は得られません。メソッドが使用する組み込み型のプロトタイプをいじる JavaScript の機能により、攻撃者はメソッドを妨害することができます。
これは私が理解している 1 つの制限であり、おそらく上記で言及する必要がありました。ただし、コードを「ハッキング」しようとする人からコードを保護するという観点からは、これを見ていません。ただし、注意すべき点がいくつかあります (または、間違っている場合は修正する必要があります)。
- 私の公開メンバーだけがこのように脆弱です。
- 私のパブリック仮想メソッドがこのように「侵害された」場合、「侵害された」メソッドはプライベートメンバーにアクセスできません。
- パブリック (非仮想) メンバーがこのように「侵害」された場合、メソッドの元のバージョンとは異なり、「侵害」されたバージョンはプライベート メンバーにアクセスできません。
- 私の知る限り、initialize メソッドの外部で定義されたメソッドによってプライベート メンバーにアクセスする唯一の方法は、一部のブラウザーが eval 呼び出しを処理する方法のバグを利用することです。