2009-07-22 4 views
1

Я знаю, что это действительно раздражает, чтобы снова прочитать эту тему. Прежде чем вы начнете копировать код, одним из решений может быть то, что я не получаю прототипы и объекты в JavaScript. Но на данный момент я думаю, .Клонирование объектов 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() (после new FOO()) должен повторить n BAR: BAR не BAR: FOO как на данный момент.

Одно из возможных решений этой проблемы является полное переписывание функции clone в чем-то вроде этого:

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

Но такой подход имеет большой недостаток, вы не можете передавать динамически созданные объекты.

Любые идеи?

+1

Что вы подразумеваете под «динамически создаваемыми объектами»? –

+0

Представьте, что вы создали экземпляр CAT внутри FOO и сохранили CAT как свойство вроде this.cat = new CAT(); И CAT Класс создал и сохранил ссылку на элемент DOM. подобный this.myBody = $("body"). –

+0

В процессе клонирования, когда вы хотите скопировать, и когда вы хотите скопировать ссылку? – Rojo

ответ

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; 

}; 

Попытайтесь вникать в него, чтобы понять, как это работает. Кто-нибудь может увидеть какие-либо проблемы с этой реализацией, утечки памяти и т. Д.?

+0

В любом случае, спасибо всем, кто помог мне! –

+0

Я думаю, что решение Кристофа - это обычный способ обращения к «клонированию» в javascript. Установите прототип фиктивной функции для объекта, который вы хотите клонировать, вызовите функцию с помощью 'new' и viola, у вас есть клон. –

0

Проблема с клонированием объекта javascript заключается в том, насколько глубоко вы решите пойти?

Рассмотрит я иметь следующий объект:

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

Это означает, что я должен был бы пройти все свойства, типа «объект», который мог бы получить довольно дорого, если у вас есть глубокая вложенность.

Если у вас есть простой объект уровня 1, вы можете просто использовать простое отражение для цикла и создать новый литерал объекта. ПРИМЕЧАНИЕ. Это не будет копировать методы исходного объекта.

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; 
    } 
} 
+0

Извините Alex, но это не решило мою проблему с динамически создаваемыми объектами. Ваш подход очень похож на мою функцию клона. –

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 
+1

Этот прототип - это мой случай неопределенного свойства, потому что объект уже создан. Я не могу вспомнить, что свойство this.prototype может существовать в инициализированном «CLASS». Если вы хотите получить прототип из уже инициализированного «CLASS», вы должны использовать аргументы. Callee.prototype. В результате вы используете прототип статического объекта вместо текущего динамического объекта. –

0

Там есть другое изменение, которое должно быть сделано, в дополнение к этому упомянутые SolutionYogi. В FOO вы передаете BAR для клонирования, но BAR - это конструктор (typeof BAR == "function"), поэтому он будет терпеть неудачу первого теста функции clone, а ваше возвращаемое значение будет ссылкой на неизменный BAR , И это означает, что myBAR.prototype не является клоном BAR.prototype, а ссылкой на него.

Для того, чтобы фактически создать новый конструктор, а не только реф, я думаю, вы должны использовать Eval - добавить что-то вроде:

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

Есть и другие соображения (Алекс указывает) , но добавив выше, должен привести к успешному выполнению вашего тестового примера.

+0

Да, это работает отлично для статического объекта, но не динамического. Представьте, что у вас есть ссылка на элемент DOM. –

+0

В какой ситуации вы предполагаете, что это приведет к BAR (конструктору), имеющему ссылку на объект DOM? – Rojo

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` 
+0

Простите Кристофу ту же проблему. В моем случае я должен динамически расширять Bar Object. –

 Смежные вопросы

  • Нет связанных вопросов^_^