Каков наиболее эффективный способ глубокого клонирования объекта в JavaScript?
Я столкнулся с этой проблемой много лет назад.
Проблема в том, что, когда вы используете свойство innerHTML для добавления HTML, после каждого обновления базовый движок закрывает закрытый тег (и исправляет другой плохой HTML) для вас. Поэтому после второй строки теги
и
автоматически закрываются, и все содержимое после этого будет просто записано вне таблицы.
Метод 1 (простой способ)
Используйте строку для хранения HTML для всей таблицы и обновите ее сразу.
var table = document.createElement('table');
table.setAttribute('border','1');
table.setAttribute('width','100%')
var row = table.insertRow(0);
for(j=1; j<=10; j++){
var text = document.createTextNode(String.fromCharCode(j+64));
var cell = row.insertCell(j-1);
cell.setAttribute('align','center')
cell.appendChild(text);
}
document.getElementById("outputDiv").appendChild(table);
2019 - примечание в июне: Это было первоначально ответом на другой ответ, не надлежащим ответом на этот вопрос. Никакая идея, почему это было выбрано как правильный ответ. Но так как upvotes разросся, и это - безусловно ответ № 1 на этот вопрос, это будет суммировать решения как ответ Wiki.
Собственный компонент глубоко клонирование
Это называют "структурированным клонированием", работает экспериментально в Узле 11 и позже, и надо надеяться приземлится в браузерах. См. этот ответ для получения дополнительной информации.
Быстрое клонирование с потерей данных - JSON.parse/stringify
, Если Вы не используете Date с, функции, undefined, Infinity, RegExps, Карты, Наборы, Блобы, FileLists, ImageDatas, разреженные массивы, Типизированные массивы или другие составные типы в Вашем объекте, очень простой один лайнер для глубокого клонирования объекта:
JSON.parse(JSON.stringify(object))
const a = {
string: 'string',
number: 123,
bool: false,
nul: null,
date: new Date(), // stringified
undef: undefined, // lost
inf: Infinity, // forced to 'null'
re: /.*/, // lost
}
console.log(a);
console.log(typeof a.date); // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date); // result of .toISOString()
Начиная с клонирования объектов, не тривиально (составные типы, циклические ссылки, функция и т.д.), большинство крупнейших библиотек обеспечивает функцию для клонирования объектов. не перестраивают колесо - если Вы уже пользуетесь библиотекой, проверьте, имеет ли оно функцию клонирования объекта. Например,
lodash - cloneDeep; может быть импортирован отдельно через модуль lodash.clonedeep и, вероятно, Ваш лучший выбор, если Вы уже не пользуетесь библиотекой, которая обеспечивает глубокую функцию клонирования
@drax Извините я don' t получают его. Вы говорите, что какой-либо шаблон функции является проблемой? What' s с, о, половина стандартной библиотеки, он бесполезный теперь потому что " Вы или авторизовываете несколько версий своей функции с типами, которые не были бы необходимый иметь смысл, или Вы явно запрещаете их, которые добавляют некоторый ужасный code"? комитет по стандартам будет удивлен услышать это.
– n.m.28 January 2014 в 17:45
Код:
// extends 'from' object with members from 'to'. If 'to' is null, a deep clone of 'from' is returned
function extend(from, to)
{
if (from == null || typeof from != "object") return from;
if (from.constructor != Object && from.constructor != Array) return from;
if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function ||
from.constructor == String || from.constructor == Number || from.constructor == Boolean)
return new from.constructor(from);
to = to || new from.constructor();
for (var name in from)
{
to[name] = typeof to[name] == "undefined" ? extend(from[name], null) : to[name];
}
return to;
}
Тест:
var obj =
{
date: new Date(),
func: function(q) { return 1 + q; },
num: 123,
text: "asdasd",
array: [1, "asd"],
regex: new RegExp(/aaa/i),
subobj:
{
num: 234,
text: "asdsaD"
}
}
var clone = extend(obj);