JavaScript DOM Nodes

JavaScript provides methods to create, add, remove, and clone DOM nodes. These methods allow you to dynamically build and modify the page structure without reloading.

createElement() and createTextNode()

document.createElement() creates a new HTML element. document.createTextNode() creates a text node. Both are created in memory and must be added to the DOM to appear on the page.

Creating Elements
// Create a new paragraph element
// const para = document.createElement('p');
// const text = document.createTextNode('Hello, World!');
// para.appendChild(text);

// Simulating element creation
function createElement(tag) {
  return { tag: tag, children: [], attributes: {} };
}

function createTextNode(text) {
  return { type: 'text', content: text };
}

const div = createElement('div');
const heading = createElement('h2');
const text = createTextNode('Hello, World!');

heading.children.push(text);
div.children.push(heading);

console.log('Created: <' + div.tag + '>');
console.log('  <' + heading.tag + '>' + text.content + '</' + heading.tag + '>');
console.log('</' + div.tag + '>');

appendChild()

The appendChild() method adds a node to the end of a parent's child list. If the node already exists in the DOM, it is moved (not copied) to the new position.

Appending Child Nodes
// const list = document.getElementById('myList');
// const newItem = document.createElement('li');
// newItem.textContent = 'New Item';
// list.appendChild(newItem);

// Simulating appendChild
const myList = { tag: 'ul', children: ['Item 1', 'Item 2'] };

console.log('Before: ' + myList.children);

myList.children.push('Item 3');
myList.children.push('Item 4');

console.log('After appendChild:');
myList.children.forEach(function(item, i) {
  console.log('  <li>' + item + '</li>');
});

console.log('Total children: ' + myList.children.length);

insertBefore()

The insertBefore() method inserts a node before a specified reference node. The syntax is parent.insertBefore(newNode, referenceNode).

Inserting Before a Node
// const list = document.getElementById('myList');
// const newItem = document.createElement('li');
// newItem.textContent = 'Inserted Item';
// const secondItem = list.children[1];
// list.insertBefore(newItem, secondItem);

// Simulating insertBefore
const items = ['First', 'Third', 'Fourth'];
console.log('Before: ' + items);

// Insert 'Second' before 'Third' (index 1)
items.splice(1, 0, 'Second');
console.log('After insertBefore: ' + items);

// Insert at the beginning
items.splice(0, 0, 'Zero');
console.log('Insert at start: ' + items);

replaceChild() and removeChild()

replaceChild() replaces a child node with a new node. removeChild() removes a child node from the DOM. Both return the removed/replaced node.

Replacing and Removing Nodes
// Replace: parent.replaceChild(newChild, oldChild)
// Remove: parent.removeChild(child)

// Simulating replaceChild and removeChild
const children = ['Old Item', 'Keep This', 'Remove Me'];

// Replace first item
const oldItem = children[0];
children[0] = 'New Item';
console.log('Replaced: "' + oldItem + '" -> "' + children[0] + '"');
console.log('List: ' + children);

// Remove last item
const removed = children.pop();
console.log('Removed: "' + removed + '"');
console.log('List: ' + children);

// Modern alternative: element.remove()
// element.remove();  // Removes itself from DOM
console.log('\nModern: element.remove() is simpler');

cloneNode()

cloneNode() creates a copy of a node. Pass true for a deep clone (includes all descendants) or false for a shallow clone (node only, no children).

Cloning Nodes
// Shallow clone: node.cloneNode(false)
// Deep clone: node.cloneNode(true)

// const original = document.getElementById('template');
// const deepCopy = original.cloneNode(true);   // With children
// const shallowCopy = original.cloneNode(false); // Without children

const original = {
  tag: 'div',
  id: 'original',
  children: ['Child 1', 'Child 2']
};

// Deep clone
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.id = 'copy';

console.log('Original children: ' + original.children);
console.log('Deep copy children: ' + deepCopy.children);

// Shallow clone
const shallowCopy = { tag: original.tag, id: 'shallow', children: [] };
console.log('Shallow copy children: ' + shallowCopy.children.length);
console.log('\ncloneNode(true) copies descendants');
console.log('cloneNode(false) copies only the node');

Document Fragments

A DocumentFragment is a lightweight container that holds DOM nodes in memory. It is used for batch operations to avoid multiple reflows when adding many elements to the DOM.

Using DocumentFragment
// Without fragment: each appendChild causes a reflow
// With fragment: one reflow when fragment is appended

// const fragment = document.createDocumentFragment();
// for (let i = 0; i < 5; i++) {
//   const li = document.createElement('li');
//   li.textContent = 'Item ' + (i + 1);
//   fragment.appendChild(li);
// }
// document.getElementById('list').appendChild(fragment);

// Simulating fragment batch operation
const fragment = [];
for (let i = 0; i < 5; i++) {
  fragment.push('Item ' + (i + 1));
}

console.log('Fragment built in memory:');
fragment.forEach(function(item) {
  console.log('  <li>' + item + '</li>');
});
console.log('Appended to DOM in one operation');
console.log('Only 1 reflow instead of 5!');
MethodDescriptionReturns
createElement(tag)Create a new elementNew element
createTextNode(text)Create a text nodeNew text node
appendChild(node)Add to end of childrenAppended node
insertBefore(new, ref)Insert before referenceInserted node
replaceChild(new, old)Replace a childReplaced (old) node
removeChild(child)Remove a childRemoved node
cloneNode(deep)Clone a nodeCloned node
element.remove()Remove self from DOMundefined
📝 Note: Always use DocumentFragment when adding multiple elements in a loop. Direct DOM manipulation in a loop causes multiple reflows, which degrades performance. The modern element.remove() method is simpler than parentNode.removeChild(element) and is supported in all modern browsers.
Exercise:
What does cloneNode(true) do?
Try it YourselfCtrl+Enter to run
Click Run to see the output here.