1

このトピックをもう一度読むのは本当に面倒です。コードを掘り下げる前に、解決策の 1 つは、JavaScript でプロトタイプとオブジェクトを取得しないことです。しかし、この時点で私はそう思います。

問題は次のとおりです:
JavaScript クラス (プロトタイプで作成) を複製して、後で拡張および実行するときに「複製された」クラスがそのまま残るようにする方法は?

function clone(obj){
  if(obj == null || typeof(obj) != 'object')
      return obj;

  var temp = new obj.constructor();
  for(var key in obj)
      temp[key] = clone(obj[key]);

  return temp;
}

var FOO = function() {
  var myBAR = clone(BAR);
  myBAR.prototype = jQuery.extend(true, myBAR.prototype, this); // deep cloning twice and extending with this
  console.log("FOO:", this.name);
  new myBAR();
};

FOO.prototype = {
  name: "FOO"
};

var BAR = function() {
  console.log("BAR:", this.name);
};

BAR.prototype = {
  name: "BAR"
};

new FOO(); // returns FOO: FOO and BAR: FOO 
new BAR(); // returns BAR: FOO should return BAR: BAR

私が正しければ、new BAR()(after )の2番目の呼び出しは、現時点でnew FOO()は返されBAR: BARないはずです。BAR: FOO

この問題の可能な解決策の 1 つは、clone関数を次のように完全に書き直すことです。

function clone(obj) {
  return eval("("+obj.toString()+")"); // the same as eval(uneval(obj));
}

しかし、このアプローチには大きな欠点があり、動的に作成されたオブジェクトを渡すことができません。

何か案は?

4

5 に答える 5

1

問題は、「プロトタイプ」のクローンを作成する方法です

次の行

myBAR.prototype = jQuery.extend(true, myBAR.prototype, this); // deep cloning 

「プロトタイプ」を複製しているだけでなく、「名前」プロパティも複製しています。

上記の行を次のように置き換えると

myBAR.prototype = jQuery.extend(true, myBAR.prototype, this.prototype); // deep cloning 

コードが返されます

new FOO(); // returns FOO:FOO and BAR:BAR
new BAR(); // returns BAR:BAR
于 2009-07-23T02:39:24.060 に答える
0

javascriptオブジェクトのクローンを作成する際の問題は、どれだけ深く進むことにしたかということです。

私が次のオブジェクトを持っていると考えてください:

var obj = { 
    prop : {
        n1prop : {
            hello : 'world';
        }
    }
};

これは、「オブジェクト」タイプのすべてのプロパティをトラバースする必要があることを意味します。これは、深いネストがある場合、非常にコストがかかる可能性があります。

単純な1レベルのオブジェクトがある場合は、単純なリフレクションforループを使用して、新しいオブジェクトリテラルを作成できます。注:これは、元のオブジェクトのメソッドをコピーしません。

function clone(obj) {
   var cloned;

   if (obj && typeof obj === 'object') {
       cloned = {};
       for (var p in obj) {
           if (obj.hasOwnProperty(p) && typeof obj[p] !== 'function') {
               cloned[p] = obj[p]
           }
       }
       return cloned;
   }
   else {
       return null;
   }
}
于 2009-07-23T01:30:51.270 に答える
0
function clone(obj) {
    if(typeof obj !== 'undefined') {
        clone.prototype = Object(obj);
        return new clone;
    }
}

function Foo() {} // base class

function Bar() {} // derived class
Bar.prototype = clone(Foo.prototype); // inherit from `Foo.prototype`
于 2009-07-23T06:47:19.423 に答える
0

SolutionYogi によって言及されたものに加えて、行う必要がある別の変更があります。FOO では、BAR を渡してクローンを作成しますが、BAR はコンストラクター (typeof BAR == "function") であるため、クローン関数の最初のテストに失敗し、戻り値は変更されていない BAR への参照になります。 . つまり、myBAR.prototype は BAR.prototype のクローンではなく、それへの参照です。

refだけでなく、実際に新しいコンストラクターを作成するには、evalを使用する必要があると思います-次のようなものを追加します。

if (typeof obj == "function) {
    eval("var temp = " + obj + ";");
    return temp;
}

(Alex が指摘しているように) 他の考慮事項がありますが、上記を追加すると、テスト ケースが成功するはずです。

于 2009-07-23T04:57:17.663 に答える
0

上記の問題に対する私の解決策を誰かに見せたかっただけです。

function cloneClass (func) {

  if(typeof func == 'function') {

    var prototype = {};
    for (var prop in func.prototype) {
      prototype[prop] = func.prototype[prop];
    };

    var Class = function() {
      var _this = this;
      var constructor = function() {
        func.apply(_this, arguments);
      };
      constructor.prototype = _this;

      for (var property in func) {
        if(property != "prototype") {
          constructor[property] = func[property];
        }
      };

      return constructor;
    };

    Class.prototype = prototype;
    return new Class();
  }

  return func;

};

これがどのように機能するかを理解するために、それを掘り下げてみてください。この実装、メモリリークなどに問題がある人はいますか?

于 2009-07-27T18:36:47.677 に答える