У меня есть два хороших ответа в зависимости от того, должна ли ваша цель клонировать «простой старый объект JavaScript» или нет.
Предположим также, что вы намерены создать полный клон без ссылок на прототипы назад к исходному объекту. Если вас не интересует полный клон, вы можете использовать многие из подпрограмм Object.clone (), предоставленные в некоторых других ответах (шаблон Крокфорда).
Для простых старых объектов JavaScript надежный и надежный способ клонирования объекта в современных средах выполнения довольно просто:
var clone = JSON.parse(JSON.stringify(obj));
Обратите внимание, что исходный объект должен быть чистым объектом JSON. Это означает, что все его вложенные свойства должны быть скалярами (например, логическими, строковыми, массивными, объектными и т. Д.). Любые функции или специальные объекты, такие как RegExp или Date, не будут клонированы.
Является ли он эффективным? Черт возьми. Мы пробовали все виды методов клонирования, и это работает лучше всего. Я уверен, что какой-нибудь ниндзя может вызвать более быстрый метод. Но я подозреваю, что мы говорим о предельных выигрышах.
Этот подход просто прост и прост в реализации. Включите его в функцию удобства, и если вам действительно нужно выжать некоторый выигрыш, идите позже.
Теперь, для не-простых объектов JavaScript, нет простого ответа. На самом деле не может быть из-за динамического характера функций JavaScript и состояния внутреннего объекта. Глубокое клонирование структуры JSON с функциями внутри требует, чтобы вы воссоздали эти функции и их внутренний контекст. И JavaScript просто не имеет стандартного способа сделать это.
Правильный способ сделать это еще раз - это метод удобства, который вы декларируете и повторно используете в своем коде. Метод удобства может быть наделен некоторым пониманием ваших собственных объектов, чтобы вы могли правильно воссоздать график в новом объекте.
Мы пишем наш собственный, но лучший общий подход. см. здесь:
http://davidwalsh.name/javascript-clone
Это правильная идея. Автор (Дэвид Уолш) прокомментировал клонирование обобщенных функций.
Основная идея заключается в том, что вам нужно специально обработать инстанцирование ваших функций (или прототипных классов, если можно так выразиться) тип основы. Здесь он предоставил несколько примеров для RegExp и Date.
Этот код не только краткий, но и очень читабельный. Это довольно легко расширить.
Это эффективно? Черт возьми. Учитывая, что цель состоит в том, чтобы создать настоящий клон с глубокой копией, вам придется ходить по членам графа исходного объекта. С помощью этого подхода вы можете точно настроить, какие дочерние элементы обрабатывать и как вручную обрабатывать настраиваемые типы.
Итак, вы идете. Два подхода. На мой взгляд, обе эффективны.
Вам это не понравится. Либо вы используете несколько переменных одного и того же типа for(Object var1 = null, var2 = null; ...)
, либо вы извлекаете другую переменную и объявляете ее перед циклом for.
Инициализация оператора for
следует правилам для объявлений локальных переменных .
Это было бы законным (если глупо):
for (int a = 0, b[] = { 1 }, c[][] = { { 1 }, { 2 } }; a < 10; a++) {
// something
}
Но попытка объявить различные Node
и int
типы, которые вам нужны, не является законной для локальных объявлений переменных.
Вы можете ограничить область дополнительных переменных внутри используя этот блок:
{
int n = 0;
for (Object o = new Object();/* expr */;/* expr */) {
// do something
}
}
Это гарантирует, что вы случайно не используете повторную переменную в другом месте метода.
Просто переместите объявления переменных (Node<T> current
, int currentIndex
) за пределы цикла, и он должен работать. Что-то вроде этого
int currentIndex;
Node<T> current;
for (current = first; current != null; current = current.next, currentIndex++) {
или, может быть, даже
int currentIndex;
for (Node<T> current = first; current != null; current = current.next, currentIndex++) {