Node#
Node.replaceChild()#
Metoda replaceChild() zastępuje przekazanym węzłem wskazywane dziecko w danym węźle i zwraca referencję do zastępowanego dziecka.
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
var child = node.replaceChild(other, child);gdzie poszczególne człony oznaczają:
- child - referencja do wskazywanego dziecka zastępowanego przekazanym węzłem.
- node - węzeł będący obiektem kontekstu, który musi być rodzicem dla wskazywanego dziecka.
- other - referencja do przekazanego węzła zastępującego wskazywane dziecko.
- child - referencja do wskazywanego dziecka zastępowanego przekazanym węzłem.
Algorytm wywołania metody replaceChild(other, child) nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
- Zwróć wynik zastępowania child przez other w obiekcie kontekstu.
Do wywołania metody replaceChild() w powyższym zapisie składniowym potrzeba trzech odwołań: do rodzica, do nowego węzła oraz do zastępowanego dziecka. Składnię można nieco uprościć ograniczając się wyłącznie do zastępowanego dziecka i nowego węzła:
var child = child.parentNode.replaceChild(other, child);
Analizując dokładnie wszystkie powiązane z metodą replaceChild() algorytmy można zauważyć, że przekazany węzeł będący pierwszym argumentem nie może istnieć jednocześnie w kilku miejscach drzewa węzłów. Najpierw zostanie usunięty z drzewa węzłów, a następnie wstawiony w nowe miejsce drzewa węzłów (z ewentualnym skorygowaniem jego właściciela). Jeśli zależy nam na wstawieniu drugiego identycznego węzła należy go najpierw sklonować i dopiero dołączyć do konkretnego drzewa węzłów. Trzeba pamiętać, że kopia nigdy nie będzie zsynchronizowana z oryginałem (są to dwa osobne obiekty), każda zmiana oryginału nie będzie miała żadnego wpływu na wykonaną kopię.
Warto podkreślić, że węzeł docelowy, na którym wywołujemy metodę replaceChild(), koniecznie musi być rodzicem dla przekazanego węzła stanowiącego drugi argument, ale nie może być jego dalszym przodkiem, w przeciwieństwie do metody Node.appendChild(), która pozbawiona jest takich ograniczeń.
Trzeba uważać przy zastępowaniu wielu węzłów za pomocą metody replaceChild(). Z racji tego, że zastąpione węzły wciąż pozostają w pamięci komputera, to w niektórych przypadkach mogą znacząco wpłynąć na wielkość zużywanej pamięci. Jeśli usuwane węzły nie będą ponownie wykorzystywane to należałoby je samodzielnie zneutralizować, np. poprzez dereferencję lub bezpośrednie usunięcie obiektu z pamięci za pomocą operatora delete.
Prosty przykład:
<!DOCTYPE html>
<html>
<head>
<script>
// Uruchom po całkowitym załadowaniu dokumentu
window.onload = function(){
var ul1 = document.getElementById("ul1");
var ul2 = document.getElementById("ul2");
var newChild = ul1.getElementsByTagName("li")[0]; // referencja do nowego dziecka
var oldChild = ul2.getElementsByTagName("li")[0]; // referencja do zastępowanego dziecka
// Manipulujemy drzewem po upływie 3 s
setTimeout(function(){
var ref = oldChild.parentNode.replaceChild(newChild, oldChild); // referencja do zastępowanego dziecka po jego zastąpieniu, to samo co oldChild
var nextNode = document.createElement("li"); // kolejny nowy węzeł
nextNode.textContent = ref; // wartością tekstową uzyskaną po automatycznej konwersji ref będzie [object HTMLLIElement]
ul2.appendChild(nextNode); // dołączenie nowego węzła
ul2.appendChild(ref); // dołączenie zastępowanego dziecka
}, 3000);
}
</script>
</head>
<body>
<p>Lista 1</p>
<ul id="ul1">
<li><a href="">Pierwszy odsyłacz</a></li>
<li><a href="">Drugi odsyłacz</a></li>
</ul>
<p>Lista 2</p>
<ul id="ul2">
<li><a href="">Pusto</a></li>
</ul>
</body>
</html>Składnia Web IDL#
interface Node : EventTarget { Node replaceChild(Node other, Node child); }