5

私はここ数日、MooToolsクラスにプライベートまたは保護されたプロパティを設定する方法を研究してきました。さまざまな記事(つまり、Sean McArthurのMooToolsクラスでのプライベート変数の取得)は、MooToolsの非推奨バージョンのアプローチを提供していますが、MooTools1.3以降の動作方法を追跡することはできませんでした。

今日、コードで何時間も遊んだ後、私は適切なソリューションを作成したと思います。私はプログラマーとしての経験があまりないので、「考える」と言います。ここのコミュニティが私のコードをチェックして、それが実際に有効なソリューションなのか、それともハックジョブエミュレーションなのかを教えてくれることを望んでいました。

var TestObj = (function() {

 var _privateStaticFunction = function() { }

 return new Class({

  /* closure */
  _privates: (function() {

   return function(key, val) {

    if (typeof(this._data) == 'undefined') this._data = {};

    /* if no key specified, return */
    if (typeof(key) == 'undefined') return;

    /* if no value specified, return _data[key] */
    else if (typeof(val) == 'undefined') {
      if (typeof(this._data[key]) != 'undefined') return this._data[key];
      else return;
    }

    /* if second argument, set _data[key] = value */
    else this._data[key] = val;

   }

  /* tell mootools to hide function */
  })().protect(),

  initialize: function() {},

  get: function(val) { return this._privates(val); },
  set: function(key,val) { this._privates(key,val); }

 })

})();


obj1 = new TestObj();
obj2 = new TestObj();

obj1.set('theseShoes','rule');
obj2.set('theseShoes','suck');

obj1.get('theseShoes') // rule
obj2.get('theseShoes') // suck
obj1._privates('theseShoes') // Error: The method "_privates" cannot be called
obj1._privates._data // undefined
obj1._privates.$constructor._data // undefined

ヒントは本当にありがたいです!みんな、ありがとう!

編集:まあ、これは恥ずかしいです。明らかなobj1._dataをチェックするのを忘れました。これがインスタンスオブジェクトを参照するとは思いませんでした。だから、私は吸う。それでも、どんなアイデアも素晴らしいでしょう!

4

1 に答える 1

4

ふふ。あなたの場合、より単純なパターンでうまくいくでしょう。

クロージャーの背後にある変数を検討してください-パンクするのは非常に困難です。ゲッターとセッターから利用できます。

欠点:データ値をインスタンスに含めることはできません。または、データ値に直接アクセスすることもできます。

var testObj = (function() {
    var data = {__proto__:null}; // 100% private

    return new Class({
        get: function(key) {
            return data[this.uid][key] || null;
        },
        set: function(key, value) {
            data[this.uid][key] = value;
        },
        remove: function(key) {
            delete data[this.uid][key];
        },
        otherMethod: function() {
            alert(this.get("foo"));
        },
        initialize: function() {
            this.uid = String.uniqueID();
            data[this.uid] = {};
        }
    });
})(); // why exec it?


var foo = new testObj();
var bar = new testObj();

foo.set("bar", "banana");
console.log(foo.get("bar")); // banana!
console.log(bar.get("bar")); // undefined.
bar.set("bar", "apple");
console.info(foo.get("bar"), bar.get("bar")); // banana apple

動作中:http://jsfiddle.net/dimitar/dCqR7/1/

私はこのパターンに穴を開ける方法を見つけるのに苦労しています-これはこのようなプロトタイピングによって達成できる場合があります。

実際、私はそれで遊んだのですが、名前空間のない固定パターンは次のとおりです。

http://jsfiddle.net/dimitar/dCqR7/2/

var testObj = (function() {
    var data = {__proto__:null}; // 100% private

    return new Class({
        get: function(key) {
            return data[key] || null;
        },
        set: function(key, value) {
            data[key] = value;
        },
        remove: function(key) {
            delete data[key];
        },
        otherMethod: function() {
            alert(this.get("foo"));
        }
    });
});


var foo = new new testObj();
var bar = new new testObj();

foo.set("bar", "banana");
console.log(foo.get("bar")); // banana!
console.log(bar.get("bar")); // undefined.
bar.set("bar", "apple");
console.info(foo.get("bar"), bar.get("bar")); // banana apple

それがなぜであるかを編集してください...

私がmootoolsに依存しているということは、ネイティブjsプロトタイプを理解しているということは、これに直接対処しなければならないことを抽象化するため、何かが望まれることを意味します。

dataパターン1では、プロトタイプを作成して設定する関数(単一のインスタンス)を定義して実行します。data次に、すでに設定されている「ライブ」プロトタイプを使用して新しい関数を作成します。

パターン2では、新しいプロトタイプが作成され、インスタンスごとに相互に独立して参照されます。関数はプロトタイプクラスを持つ新しい関数を返します...したがって、実際new Class({});new new <var>()はクラスを作成してインスタンス化します。

これをよりよく理解するために、おそらく最初に次のように書くことができます-再利用されていないクラスを作成してインスタンス化するための一般的な十分なパターン-これはより理にかなっています:

new (new Class({
    initialize: function() {
        alert("hi");
    }
}))();

これは次のように書くことができます(変数に保存されている場合):

var foo = new Class({
    initialize: function() {
        alert("hi");
    }
});

new foo();

私はそれが理にかなっていることを願っています、私は説明するのに最高の人ではありません...

于 2011-05-23T23:56:29.950 に答える