Node#
Node.cloneNode()#
Metoda cloneNode()
kopiuje dany węzeł i zwraca referencję do nowej kopii.
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
var cloned = node.cloneNode([deep = false
]);
gdzie poszczególne człony oznaczają:
- cloned - referencja do skopiowanego węzła.
- node - węzeł będący obiektem kontekstu.
deep - opcjonalny boolowski parametr determinujący rodzaj kopii:
true
- oznacza kopię głęboką (deep copy), gdzie kopiowany będzie węzeł ze wszystkimi jego dziećmi.false
- oznacza kopię płytką (shallow copy), gdzie kopiowany będzie jedynie węzeł, bez jego dzieci (nawet z wykluczeniem węzłów tekstowych). Jest to wartość domyślna i zostanie automatycznie przekazana w przypadku braku argumentu w wywołaniu metody lub w chwili, kiedy przekazany argument należy do jednej z wartości negatywnych (np. dlaundefined
czynull
).
Algorytm wywołania metody cloneNode(deep)
nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
- Zwróć wynik klonowania dla obiektu kontekstu oraz, jeśli deep ma boolowską wartość
true
, z ustawieniem flagi klonowania dzieci.
Możliwość pominięcia argumentu dla metody cloneNode()
została wprowadzona dopiero w specyfikacji DOM4. Podobnie jest z domyślnym zachowaniem preferującym kopię płytką, która po kolejnej aktualizacji specyfikacji zastąpiła domyślną kopię głęboką (DOM - Bug 23565). Warto zaznaczyć, że dla elementów pustych (nie zawierających żadnej zawartości), np. <img>
czy <input>
, nie ma znaczenia jaka wartość zostanie przekazana do metody.
Węzeł zwracany przez metodę cloneNode()
zostaje skopiowany (opcjonalnie z całą swoją zawartością) z poprzedniego drzewa węzłów, ale nie jest częścią w nowym drzewie dokumentu dopóki nie zostanie dodany do innego węzła należącego do drzewa dokumentu. Dlatego samotna kopia nie będzie posiadała rodzica (wartość null
), aczkolwiek dalej posiada jakiegoś właściciela.
Do skopiowania węzła z jednoczesną zmianą jego właściciela służy metoda Document.importNode()
.
Kopiowanie węzłów jest bardzo pożyteczne i w niektórych okolicznościach pozwala zwiększyć wydajności tworzonych skryptów. Mając rozległą strukturę węzłową szybciej odtworzymy ją za pomocą kopiowania, niż gdybyśmy ręcznie tworzyli każdy węzeł z takiej struktury.
Prosty przykład:
<script>
var newEl = document.createElement("div");
newEl.innerHTML = "<p>Pierwsze dziecko.</p><p>Drugie dziecko.</p>";
document.write(newEl.cloneNode().childNodes.length); // 0 (kopia płytka)
document.write("<br>");
document.write(newEl.cloneNode(false).childNodes.length); // 0 (kopia płytka)
document.write("<br>");
document.write(newEl.cloneNode(0).childNodes.length); // 0 (kopia płytka)
document.write("<br>");
document.write(newEl.cloneNode("").childNodes.length); // 0 (kopia płytka)
document.write("<br>");
document.write(newEl.cloneNode(undefined).childNodes.length); // 0 (kopia płytka)
document.write("<br><br>");
document.write(newEl.cloneNode(true).childNodes.length); // 2 (kopia głęboka)
document.write("<br>");
document.write(newEl.cloneNode("false").childNodes.length); // 2 (kopia głęboka)
document.write("<br>");
document.write(Boolean("false")); // true
</script>
Warto zwrócić uwagę na warianty, gdzie metodzie cloneNode()
przekazano argumenty innego typu niż boolowskie true
lub false
. Jest to jak najbardziej prawidłowe, wartości te zostaną automatycznie skonwertowane przez maszynę JS na odpowiadającą wartość boolowską. Można porównać z ręcznym wymuszeniem konwersji zaprezentowanym w ostatniej linijce przykładu.
Składnia Web IDL#
interface Node : EventTarget { Node cloneNode(optional boolean deep = false); }