3

モジュールを公開しようとしています。そのインスタンスを 1 つだけすべての呼び出し元に公開し、モジュールが呼び出されてインスタンス化されるまで待機したいと考えています。私はこれをやろうとしました:

var obj = {};

var foobar = function(){
 var id=22;
 function GetId(){ return ++id; }
 return{ GetId: GetId };
};

obj.foobar = (function(){
    if (obj.foobar instanceof foobar) {
         return obj.foobar;
    }
    return new foobar();
})();

console.log(obj.foobar.GetId());//23
console.log(obj.foobar.GetId());//24

しかし、実際にはそれは難読化にすぎません

obj.foobar = new foobar();

私が意図していたのは、 が初めて呼び出されたobj.foobar = new foobar()ときにインスタンス化することでした。2 回目は、既にインスタンス化されたバージョンを使用して呼び出されました。ここにはありませんが、インスタンス化を待機する必要があるため、すぐに実行できない依存関係があります。obj.foobar.GetId()obj.foobar.GetId()new foobar();

どうすればこれを達成できますか、何が欠けていましたか?

4

2 に答える 2

4

アクセスするたびに関数呼び出しを使用できますfoobar

obj.foobar = (function() {
  var inst;
  return function() {
    return inst || (inst = foobar());
  };
})();

console.log(obj.foobar().GetId()); // 23

対象の実行環境でサポートされている場合は、ECMAScript 5 の名前付きアクセサー プロパティを使用することもできます。

Object.defineProperty(obj, "foobar", {
  get: (function() {
    var inst;
    return function() {
      return inst || (inst = foobar());
    };
  })()
});

console.log(obj.foobar.GetId()); // 23

または、 で呼び出すことができるメソッドのリストを知っていればfoobar、より複雑なソリューションを使用できます。

obj.foobar = (function() {
  var inst, res = {}, methods = ["GetId"];
  function createLazyMethod(method) {
    return function() {
      if (!inst) {
        obj.foobar = inst = foobar();
      }

      return inst[method].apply(inst, methods.slice.call(arguments, 0));
    };
  }

  for (var i = 0; i < methods.length; ++i) {
    res[methods[i]] = createLazyMethod(methods[i]);
  }

  return res;
})();

console.log(obj.foobar.GetId()); // 23

このソリューションでは、いったんfoobarインスタンス化されると、そのメソッドへの呼び出しはゼロ コストで行われます。

于 2012-11-14T21:52:28.777 に答える
2

私が意図していたのは、初めて呼び出されたobj.foobar = new foobar()ときにインスタンス化することでしたobj.foobar.GetId()

いいえ、うまくいきません。メソッドを呼び出す場合getId、既存のオブジェクトが存在している必要があります。foobarアクセス時にインスタンスを作成するプロパティのゲッター関数を定義するか、obj以前にインスタンス化するだけです(IEFEで行ったように、割り当てを短くすることができます)。

通常、毎回呼び出す関数 (コンストラクターの場合もあります) を使用し、既に作成されている場合はシングルトンを返し、そうでない場合はシングルトンを作成して保存します。

var obj = {
    foobar: (function iefe() {
        var id, instance;
        return function constructor() {
            if (!instance) { // create it
                id = 22;
                instance = {
                    getId: function getID(){
                        return ++id;
                    }
                };
            }
            return instance;
        };
    })();
};

obj.foobar().getId() // 23
obj.foobar().getId() // 24
于 2012-11-14T21:50:50.513 に答える