Почему jQuery Extend Deep Copy не копирует объект рекурсивно?

Я искал везде и нашел похожие вопросы с ответами, которые на самом деле не касались моей проблемы, поэтому я извиняюсь, если это похоже на повторение, но из моих экспериментов следует, что функция глубокого копирования jQuery на самом деле не работает, как это описано (или возможно, я неправильно читаю его описание).

Вот пример, демонстрирующий мою проблему: http://jsfiddle.net/wcYsH/

Или это для загрузки: https://github.com/kevroy314/jQuery-Extend-Test

Почему данные в предыдущей копии изменяются при манипулировании глубокой копией?


person user986122    schedule 08.05.2012    source источник
comment
Вы хотите вместо этого использовать .clone jQuery?   -  person Explosion Pills    schedule 08.05.2012
comment
Недавно на форумах jQuery была тема об этом. Я думаю, что ваш вариант использования выходит за рамки метода $.extend. forum.jquery.com/topic/   -  person Kevin B    schedule 08.05.2012
comment
Вот соответствующая заявка на ошибку bugs.jquery.com/ticket/10014.   -  person Kevin B    schedule 08.05.2012
comment
Так рада, что я не схожу с ума! Сначала я исследовал jQuery .clone, но увидел этот ответ на аналогичный вопрос и решил сначала попробовать.   -  person user986122    schedule 08.05.2012
comment
Обновление: похоже, что .clone не будет клонировать мой тип объекта. Только DOM-объекты. Я думаю, что лучшее решение сейчас — написать функцию клонирования для каждого из моих объектов и позволить им самим заниматься саморепликацией.   -  person user986122    schedule 09.05.2012


Ответы (1)


Во-первых, вы не создаете обычные объекты.

Я просматриваю исходный код jQuery 1.7.2 для расширения.

https://github.com/jquery/jquery/blob/master/src/core.js

И я замечаю строку:

if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy))

должен оцениваться как true для выполнения глубокого копирования. копия — это просто часть текущего копируемого объекта.

Но вы не создаете «простые» объекты. Вы создаете объекты, сгенерированные вызовом конструктора с оператором new.

Теперь в isPlainObject кажется, что эти строки должны быть оценены. (где hasOwn равно hasOwn = Object.prototype.hasOwnProperty

    try {
        // Not own constructor property must be Object
        if ( obj.constructor &&
            !hasOwn.call(obj, "constructor") &&
            !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
            return false;
        }
    } catch ( e ) {
        // IE8,9 Will throw exceptions on certain host objects #9897
        return false;
    }

И здесь делается вывод, что это не «plainObject».

Это имеет смысл, если учесть, что объекты с конструктором, вероятно, должны создаваться с помощью этого конструктора или, по крайней мере, использовать какой-то метод "клонирования", как вы видите в других языках/фреймворках.

person JayC    schedule 08.05.2012
comment
Спасибо! Это то объяснение, которое я искал. Я пошел дальше и написал функцию .clone для каждого созданного объекта. К сожалению, хакерский способ, которым я использовал .extend, по-видимому, копировал объекты достаточно глубоко, чтобы мое приложение работало, но достаточно поверхностно, чтобы не тратить память, так что теперь моя реализация ужасно пожирает память! Вернуться к доске для рисования! - person user986122; 09.05.2012