CloneNode: примеры (JAVASCRIPT)

Руководство по работе с функцией cloneNode в JavaScript
Раздел: DOM, Клонирование
cloneNode(deep?: boolean): Node

Метод cloneNode в JavaScript: основы

Метод cloneNode() принадлежит интерфейсу Node в DOM и используется для создания копии узла, на котором он вызывается. Это средство дублирования элементов документа, включая их атрибуты. Применение метода актуально при необходимости повторного использования существующей структуры узлов без повторного создания через JavaScript.

Синтаксис метода: node.cloneNode(deep). Он принимает один необязательный параметр:

  • deep (булево значение): определяет глубину клонирования. Если передано true, узел клонируется со всем поддеревом потомков. При значении false или отсутствии параметра копируются только сам узел и его атрибуты, без дочерних элементов.

Возвращаемое значение — новый объект Node, который является копией исходного узла. Клонированный узел не имеет родителя (свойство parentNode равно null) и не вставляется автоматически в документ. Копия сохраняет значения атрибутов, включая обработчики событий, добавленные через атрибуты HTML, но обработчики, назначенные через свойства (например, node.onclick) или addEventListener, не копируются.

Простые примеры использования cloneNode

Клонирование элемента списка без потомков:

const list = document.getElementById('myList');
const shallowCopy = list.cloneNode(false);
console.log(shallowCopy.outerHTML);
<ul id="myList"></ul>

Глубокое клонирование элемента со всем содержимым:

const list = document.querySelector('ul');
list.innerHTML = '<li>Пункт 1</li>';
const deepCopy = list.cloneNode(true);
console.log(deepCopy.outerHTML);
<ul><li>Пункт 1</li></ul>

Клонирование с обработчиком события в атрибуте:

const btn = document.createElement('button');
btn.setAttribute('onclick', 'alert("Клик!");');
btn.textContent = 'Нажми';
const clonedBtn = btn.cloneNode(true);
document.body.appendChild(clonedBtn);
// Нажатие на кнопку вызовет alert

Альтернативные методы в JavaScript

  • document.createElement() с последующим копированием свойств: позволяет создать элемент с нуля, но требует ручного копирования атрибутов и стилей. Подходит для создания новых элементов, отличающихся от существующих.
  • innerHTML или outerHTML: присвоение строки HTML другому элементу. Метод быстр для копирования структуры, но не сохраняет обработчики событий и ссылки на исходные узлы.
  • importNode(): метод документа для импорта узлов из другого документа. Работает аналогично cloneNode(), но предназначен для узлов из внешних документов, например, из элемента iframe.

cloneNode() предпочтительнее, когда нужно точно скопировать существующий узел вместе с атрибутами, особенно если он уже присутствует в DOM. Для создания элементов по шаблону из строки удобнее использовать innerHTML.

Распространенные ошибки

Забывают, что клонированный узел не добавляется автоматически в DOM:

const div = document.createElement('div');
div.textContent = 'Текст';
const clonedDiv = div.cloneNode(true);
// Ошибка: clonedDiv не виден на странице, пока не будет добавлен
// document.body.appendChild(clonedDiv);

Ожидание копирования обработчиков событий, назначенных через addEventListener:

const btn = document.createElement('button');
btn.addEventListener('click', () => alert('Клик!'));
const clonedBtn = btn.cloneNode(true);
clonedBtn.click(); // Ничего не произойдет

Изменение id у клонированного элемента, чтобы избежать дублирования:

const elem = document.getElementById('unique');
const clone = elem.cloneNode(true);
clone.id = 'unique-clone'; // Рекомендуется

Изменения в спецификации

Метод cloneNode() существует с ранних версий DOM. Современные браузеры следуют спецификации DOM Living Standard. Существенных изменений в последние годы не было, но важно отметить, что в спецификации уточнено поведение для пользовательских элементов (Custom Elements). В стандарте Web Components, при клонировании, атрибуты и свойства копируются, но конструктор пользовательского элемента не вызывается.

Расширенные примеры

Клонирование таблицы с данными:

Пример javascript
const table = document.querySelector('table');
const newTable = table.cloneNode(true);
newTable.id = 'table-copy';
document.body.appendChild(newTable);
// Все строки и ячейки скопированы

Создание шаблонов через template и их клонирование:

Пример javascript
const template = document.getElementById('cardTemplate');
const content = template.content.cloneNode(true); // Клонирование содержимого template
content.querySelector('.title').textContent = 'Название';
document.body.appendChild(content);

Глубокое клонирование с исключением определенных элементов:

Пример javascript
function cloneWithoutClass(original, className) {
    const clone = original.cloneNode(true);
    const elementsToRemove = clone.querySelectorAll(`.${className}`);
    elementsToRemove.forEach(el => el.remove());
    return clone;
}
// Использование:
const originalDiv = document.querySelector('.container');
const cleanClone = cloneWithoutClass(originalDiv, 'remove-me');

Копирование элемента с сохранением данных из data-атрибутов:

Пример javascript
const elem = document.createElement('div');
elem.dataset.id = '123';
const clone = elem.cloneNode(true);
console.log(clone.dataset.id); // '123'

Аналоги в других языках программирования

PHP: функция clone создает поверхностную копию объекта. Для DOM используется метод cloneNode в классе DOMNode.

$dom = new DOMDocument();
$dom->loadHTML('<div>Текст</div>');
$node = $dom->getElementsByTagName('div')->item(0);
$clonedNode = $node->cloneNode(true);
echo $dom->saveHTML($clonedNode);
<div>Текст</div>

Python (библиотека lxml): метод copy для элемента.

from lxml import etree
html = etree.fromstring('<p>Пример</p>')
copy = html.copy()
print(etree.tostring(copy).decode())
<p>Пример</p>

C# (Windows Forms): метод Clone для контролов или узлов XML.

XmlDocument doc = new XmlDocument();
doc.LoadXml("<root><item/></root>");
XmlNode node = doc.SelectSingleNode("//item");
XmlNode cloned = node.Clone();

JS cloneNode function comments

En
CloneNode Returns a duplicate of the node on which it is called.