JS advanced programming (14)


The document object model (DOM) is a programming excuse for HTML and XML documents. DOM represents a document composed of multiple nodes, through which developers can add, delete and modify various parts of the page.

1, Node level

Any HTML and XML document can be represented in DOM as a hierarchy of nodes. Nodes are divided into many types. Each type corresponds to different information or tags in the document. It also has its own different characteristics, data and methods, and has some relationship with other types. These relationships form a hierarchy so that tags can represent a tree structure rooted at a specific node.

The document node represents the root node of each document. Here, the only child node of the root node is the < HTML > element, which is called a document element. The document element is the outermost element of the document, and all other elements exist within this element. Each document can have only one document element.

1.Node type

Node is implemented as node type in JavaScript, which can be accessed directly in all browsers except IE. In JavaScript, all node types inherit the node type, so all types share the same basic properties and methods.
Each Node has a nodeType attribute, which indicates the type of the Node. The Node type is represented by 12 numeric constants on the defined Node type:

  • Node.ELEMENT_NODE(1)
  • Node.TEXT_NODE(3)
  • Node.ENTITY_NODE(6)
  • Node.COMMENT_NODE(8)
  • Node.NOTATION_NODE(12)

nodeName and nodeValue
nodeName and nodeValue hold information about nodes. The values of these two attributes depend entirely on the node type.
Node relationship
All nodes in the document are related to other nodes. Each node has a childNode attribute, which contains an instance of NodeList. NodeList is an array like object that stores ordered nodes that can be accessed by location.
Each node has a parentNode attribute that points to the parent element in the DOM tree. All nodes in childNode have the same parent element, so their parentNode attribute points to the same node. In addition, each node in the childNodes list is a sibling node of other nodes in the same list. Using previousSibling and nextSibling, you can navigate between the nodes of this list.
The parent node and its first and last child nodes also have special attributes: firstChild and lastChild point to the first and last child nodes respectively.

If the hasChildNodes() method returns true, it indicates that the node has one or more child nodes. The ownerDocument property is a pointer to the document node that represents the entire document.

Operation node
appendChild() is used to add a node at the end of the childNodes list and return the newly added node.
The code is as follows (example):

//Add new node
let returnedNode=someNode.appendChild(newNode);
//Existing node transfer
let returnedNode=someNode.appendChild(someNode.firstChild);

The insertBefore() method places the node at a specific location in childNodes and receives two parameters: the node to be inserted and the reference node. The inserted node will become the previous sibling node of the reference node. If the reference node is null, it will be placed last.
The appendChild() and insertBefore() methods do not delete any existing nodes when inserting nodes.
The code is as follows (example):

//Insert as the last child node
//Insert as new first child node
//Insert last child node signature

The replaceChild() method takes two parameters: the node to insert and the node to replace. The node to be replaced is returned and completely removed from the document tree, and the node to be inserted is replaced. After inserting a node with replaceChild(), all relationship pointers will be copied from the replaced node.
The code is as follows (example):

//Replace first child node
let returnedNode=someNode.replaceChild(newNode,someNode.firstChild);
//Replace last child node
let returnedNode=someNode.replaceChild(newNode,someNode.lastChild);

The removeChild() method removes the node and receives a parameter, that is, the node to be removed.
The code is as follows (example):

//Delete the first child node
let formerFirstNode=someNode.removeChild(someNode.firstChild);
//Delete the last child node
let formerLastNode=someNode.removeChild(someNode.lastChild);

Other methods
cloneNode() returns as like as two peas of the node calling it, and receives a Boolean parameter to indicate whether the copy is deep. When the true parameter is passed in, a deep copy will be performed, that is, the node and its entire sub DOM tree will be copied. If false is passed in, only the node that calls the method will be copied. The node returned by replication belongs to the document, but the parent node has not been specified, so it is called an orphan node.
The normalize() method handles text nodes in the document subtree.

2.Document type

The document type is the type that represents the document node in JavaScript. In the browser, the document object document is an instance of HTMLDocument (HTMLDocument inherits document) and represents the entire HTML page. Document is a property of the window object, so it is a global object. The document object can be used to get information about a page and manipulate its appearance and underlying structure. A document node has the following characteristics:

  • nodeType equals 9
  • nodeName value is "#document"
  • nodeValue value is null
  • parentNode value is null
  • The ownerDocument value is null
  • The child node can be of DocumentType (at most one), Element (at most one), ProcessingInstruction or Comment type.

1. Document sub node
DOM provides two shortcuts to access child nodes. The first is the documentElement attribute, which always points to the < HTML > element in the HTML page. Another possible child node of Document type is DocumentType. <! The doctype > tag is an independent part of the Document, and its information can be accessed through the doctype attribute.
document also has a body attribute that directly points to the < body > element.

let body=document.body;//Gets a reference to < body >

2. Document information
document also provides information about the page loaded by the browser. The first attribute is title, which contains the text of the < title > element, usually displayed in the title bar of the browser window or tab. You can read and write the title of the page through this attribute. The modified title will also be reflected in the browser title bar, but modifying the title attribute will not change the < title > element.
The code is as follows (example):

//Read document title
let originalTitle=document.title;
//Modify document title
document.title="New page title";

document also has three attributes: URL, domain and reference. Where, the URL contains the full URL of the current page (the URL in the address), domain contains the domain name of the page, and referrer contains the URL of the page linked to the current page.
The code is as follows (example):

//Get full URL
let url=document.URL;
//Get domain name
let domain=document.domain;
//Source of acquisition
let referrer=document,referrer;

3. Positioning elements
The getElementById() and getElementsByTagName() methods can get a reference to an element or a group of elements.
The getElementById() method accepts a parameter, that is, to get the ID of the element. If it is found, it returns this element. If it is not found, it returns null. The parameter ID must exactly match the ID attribute of the element in the page, including case.
The code is as follows (example):

<div id="myDiv">Some text</div>

let div=document.getElementById("myDiv");//Get a reference to this < div > element
let div=document.getElementById("mydiv");//null

The getElementsByTagName () method receives a parameter, that is, to get the tag name of the element and return a NodeList containing zero or more elements. In an HTML document, this method returns an HTML collection object. To get all the elements of the document, you can pass an asterisk (*) to getElementsByTagName().
The code is as follows (example):

let images=document.getElementsByTagName("img");
alert(images.length);//Number of pictures
alert(images[0].src);//src attribute of the first picture
//Additional methods are obtained through the properties of the tag
<img src="myimage.gif" name="myImage">
let myImage=images.namedItem("myImage");

The getElementsByName() method returns all elements with the given name attribute, the longest for radio buttons.

4. Special collection

  • document.anchors: contains all < a > elements with name attribute in the document.
  • document.applets: contains all < applet > elements in the document (obsolete).
  • document.forms: contains all < form > elements in the document.
  • document.images: contains all < img > elements in the document.
  • document.links: contains all < a > elements with href attributes in the document.

5.DOM compatibility test
The hasFeature() method accepts two parameters: a special name and a DOM version. The hasFeature() method returns true if the browser supports the specified feature and version.

6. Document writing
The document object can write content to the web page output stream by four methods: write(), writeln(), open() and close(). The write() and writeln() methods both receive a string parameter, which can be written to the web page during page loading. If document.write() is called after page loading, the output content overwrites the whole page. write() simply writes text, and writeln() appends a newline character to the end of the string.
The code is as follows (example):

//write will be written in one line
document.write("Hello World!");
document.write("Have a nice day!");

The code is as follows (example):

//writeln branch
document.writeln("Hello World!");
document.writeln("Have a nice day!");

The open() and close() methods are used to open and close the web page output stream, respectively.

3.Element type

Element represents an XML or HTML element, which exposes the ability to access element tag names, child nodes and attributes.
A node of type Element has the following characteristics:

  • nodeType equals 1
  • The nodeName value is the label name of the element
  • nodeValue value is null
  • The parentNode value is a Document or Element object
  • Child nodes can be Element, Text, Comment, ProcessingInstruction, CDATASection, EntityReference types

1.HTML elements
All HTML elements are represented by the HTMLElement type, including their direct and indirect instances. HTMLElement directly inherits Element and adds some properties. Each attribute has one of the following attributes, which are standard attributes on all HTML elements:

  • id, the unique identifier of the element in the document
  • The title, which contains additional information about the element, is usually displayed in the form of a prompt bar
  • lang, language code of element content
  • dir, writing direction of language
  • className, equivalent to the class attribute, is used to specify the CSS class of the element

The code is as follows (example):

<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div>
let div=document.getElementById("myDiv");
//Read element attributes
alert(div.name);//Body text
//Modify element attributes

2. Get attributes
Each element has zero or more attributes, which are usually used to attach more information to the element or other content, including three methods: getAttribute(), setAttribute(), and removeaattribute().
The code is as follows (example):

//getAttribute() is mainly used to get custom attributes
<div id="myDiv" class="bd"  my_special_attribute="hello"></div>
let div=document.getElementById("myDiv");

3. Set properties
The setAttribute() method takes two parameters: the name of the attribute to be set and the value of the attribute. If the property already exists, replace the original value; otherwise, create the property with the specified value.
The code is as follows (example):


You can also set the value of the element attribute by directly assigning a value to the attribute of the DOM object. Adding a custom attribute to a DOM object will not automatically make it an attribute of the element:

//Custom properties

4.attributes attribute
The Element type is the only DOM node type that uses the attributes attribute. The attributes attribute contains a NamedNodeMap instance, which is a "real-time" collection similar to NodeList. The most useful scenario for the attributes attribute is when all attributes on an Element need to be iterated.
The NamedNodeMap object contains the following methods:

  • getNamedItem(name) returns the node whose nodeName attribute is equal to name
  • removeNamedItem(name), delete the node whose nodeName attribute is equal to name
  • setNamedItem(name) to add a node node to the list, with its nodeName as the index
  • item(pos), which returns the node at the index position pos

5. Create element
The document.createElement() method creates a new element, but you need to add the element to the tree.

4.Text type

The Text node is represented by the Text type. It contains literal plain Text or escaped HTML characters, but does not contain HTML code. A node of type Text has the following characteristics:

  • nodeType equals 3
  • nodeName value is "#text"
  • The nodeValue value is the text contained in the node
  • The parentNode value is an Element object
  • Child nodes are not supported

How to manipulate text:

  • appendData(text) to add text to the end of the node
  • deleteData(offset,count) deletes count characters from the position offset
  • insertData(offset,text), insert text at position offset
  • replaceData(offset,count,text), replace the text from offset to offset+count with text
  • splitText(offset) splits the current text node into two text nodes at offset
  • substringData(offset,count) to extract text from position offset to offset+count

1. Create a text node
document.createTextNode() can be used to create a new text node. It receives a parameter, that is, the text to be inserted into the node.
The code is as follows (example):

let element=document.createElement("div");
let textNode=document.createTextNode("Hello World");

2. Normalized text node
When the normalize() method is called on a parent node containing two or more adjacent text nodes, all sibling text nodes will be merged into one text node.
The code is as follows (example):

let element=document.createElement("div");
let textNode=document.createTextNode("Hello World");
let anotherTextNode=document.createTextNode("yippee!");
alert(element.firstChild.nodeValue);//"Hello World!yippee!"

3. Split text node
The splitText() method can split nodeValue at the specified offset position, and split a text node into two text nodes. After splitting, the original text node contains the text from the beginning to the offset position, and the new text node contains the remaining text. This method returns the new node.
The code is as follows (example):

let element=document.createElement("div");
let textNode=document.createTextNode("hello world!");
let newNode=element.firstChild.splitText(5);
alert(newNode.nodeValue);//" world"

5.Comment attribute

DOM comments are represented by the Comment type. A node of type Comment has the following characteristics:

  • nodeType equals 8
  • nodeName value is "#comment"
  • The nodeValue value is the comment content
  • The parentNode value is a Document or Element object
  • Child nodes are not supported

Comment type inherits the same base class as Text type, so it has all string operation methods of Text node except splitText(). Annotation nodes can be accessed as children of the parent node.
The code is as follows (example):

<div id="myDiv"><!-- A comment --></div>
let div=document.getElementById("myDiv");
let comment=div.firstChild;
//Create annotation node
let comment=document.createComment("A comment");

6.CDATASection attribute

The CDATASection type represents a unique CDATA chunk in XML. CDATASection type inherits Text type, so it has all string operation methods including splitText(). Nodes of type CDATASection have the following characteristics:

  • nodeType equals 4
  • nodeName value is "#cdata-section"
  • The nodeValue value is the content of the CDATA block
  • The parentNode value is a Document or Element object
  • Child nodes are not supported

7.DocumentType property

The DocumentType node contains the document type information of the document, which has the following characteristics:

  • nodeType equals 10
  • The nodeName value is the name of the document type
  • nodeValue value is null
  • The parentNode value is a Document object
  • Child nodes are not supported

8.DocumentFragment property

The DocumentFragment type is the only type that does not have a corresponding representation in the tag. DOM defines a document fragment as a "lightweight" document, which can contain and manipulate nodes without the additional consumption of a complete document. The DocumentFragment node has the following characteristics:

  • nodeType equals 11
  • nodeName value '#document fragment'
  • nodeValue value is null
  • parentNode value is null
  • Child nodes can be Element, ProcrssingInstruction, Comment, Text, CDATASection, or EntityReference

You cannot add a document fragment directly to a document. The purpose of a document fragment is to act as a repository for other nodes to be added to the document.
The code is as follows (example):

<ul id="myList"></ul>

let fragment=document.createDocumentFragment();
let ul=document.getElementById("myList");
for(let i=0;i<3;++i){
  let li=document.createElement("li");//Create li element
  li.appendChild(document.createTextNode(`Item ${i+1}`));//Create add text node
  fragment.appendChild(li);//Add to text fragment
ul.appendChild(fragment);//Add a text fragment to a ul element

9.Attr attribute

The element data is represented in the DOM by the attr type. Attr type constructors and prototypes are directly accessible in all browsers.
Attr node has the following characteristics:

  • nodeType equals 2
  • nodeName value property name
  • The nodeValue value is the property value
  • parentNode value is null
  • Child nodes are not supported in HTML
  • In XML, the child node can be Text or EntityReference

2, DOM programming

1. Dynamic script

There are two ways to dynamically add scripts to web pages through < script >: introducing external files and directly inserting source code.
The code is as follows (example):

//Dynamically load external files
<script src="foo.js"></script>
//DOM programming creation
let script=document.createElement("script");
//Abstract function
function loadScript(url){
  let script=document.createElement("script");

//Embedded source code
  function sayHi(){
//DOM is implemented in Firefox, Safair, Chrome, and Opera
let script=document.createElement("script");
script.appendChild(document.createTextNode("function sayHi(){alert('hi');}"));
//Abstract as a cross browser function
function loadScriptString(code){
  var script=document.createElement("script");

2. Dynamic style

CSS styles can be loaded in HTML pages through < link > and < style >.
The code is as follows (example):

//External link loading
<link rel="stylesheet" type="text/css" href="styles.css">
//DOM programming link
let link=document.createElement("link");
let head=document.getElementsByTagName("head")[0];
//Abstract as a general function
function loadStyles(url){
  let head=document.getElementsByTagName("head")[0];
//Embedded style loading
<style type="text/css">
//DOM programming in embedded fieldox, Safair, Chrome and Opera
let style=document.createElement("style");
let head=document.getElementsByTagName("head")[0];
//General function
function loadStyleString(css){
  let style=document.createElement("style");
  let head=document.getElementsByTagName("head")[0];

3. Operation form

To facilitate the creation of tables, HTML DOM adds some attributes and methods to < Table >, < tbody >, < tr > elements.
The < Table > element adds the following attributes and methods:

  • Caption, pointer to the < caption > element (if present)
  • tBodies, HTMLCollection containing < tbody > elements
  • TFoot, pointing to the < tFoot > element (if present)
  • tHead, pointing to the < tHead > element (if present)
  • Rows, which contains an HTML collection representing all rows
  • Createhead(), create the < thead > element, put it in the table, and return the reference
  • createTFoot(), create the < tFoot > element, put it in the table, and return the reference
  • createCaption(), create the < caption > element, put it in the table, and return the reference
  • Deletethread(), delete the < thead > element
  • deleteTFoot(), delete the < tFoot > element
  • deleteCaption(), delete the < caption > element
  • deleteRow(pos) to delete a row at a given location
  • insertRow(pos), inserts a row at a given position in the row set

The < tbody > element adds the following attributes and methods:

  • Rows, an HTML collection containing all rows in the element
  • deleteRow(pos) to delete a row at a given location
  • insertRow(pos), which inserts a row at a given position in the row set and returns the reference of the row

The < TTR > element adds the following attributes and methods:

  • cells, HTMLCollection containing all table elements of < tr > element
  • Delete cell (POS) to delete a table element at a given location
  • insertCell(pos) inserts a table element at a given position in the table element set and returns the reference of the table element

The code is as follows (example):

//Create table
let table=document.createElement("table");
//Create table body
let tbody=document.createElement("tbody");
//Create first row
tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1,1"));
tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 2,1"));
//Create second row
tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 1,2"));
tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 2,2"));
//Add table to body of document

4. Use NodeList

The three collection types of NodeList, NamedNodeMap and HTMLCollection are "real-time". The of a location document structure will be reflected in them in real time, so their values always represent the latest state. In fact, NodeList is a real-time query based on DOM documents.

3, MutationObserver interface

The MutationObserver interface can call back asynchronously when the DOM is modified. Using MutationObserver, you can observe the entire document, a part of the DOM tree, or an element. In addition, you can also observe the changes of element attributes, child nodes, text, or any combination of the first three.

1. Basic usage

The instance of MutationObserver is created by calling the MutationObserver constructor and passing in a callback function.

let observer=new MutationObserver ( () => console.log('DOM was mutated!'));

1.observe() method
The newly created MutationObserver instance will not be associated with any part of the dom. You need to use the observe() method. This method takes two required parameters: the DOM node to observe its change, and a MutationObserverInit object. The MutationObserverInit object is used to control which changes are observed. It is a dictionary of key / value pair configuration options.
If you want to observe any attribute change on the element, it will be found and the callback function will be executed. However, the modification of the descendant of the element and other non attribute modifications will not trigger the callback to enter the task queue.
The code is as follows (example):

let observer=new MutationObserver( () => console.log('<body> attributes changed'));
console.log('Changed body class'); 
//Changed body class
//<body> attributes changed
//The callback does not execute synchronously with the actual DOM changes

2. Callback and MutationRecord
Each callback will receive an array of MutationRecord instances. The MutationRecord instance contains information about what has changed and which part of the DOM has been affected.
The code is as follows (example):

let observer=new MutationObserver(
    (mutationRecords) => console.log(mutationRecords));
//    {
//      addedNodes:NodeList[],
//      attributeName:"foo",
//      attributeNamespace:null
//      nextSibling:null,
//      oldValue:null,
//      previousSibling:null,
//      removedNodes:NodeList[],
//      target:body
//      type:"attributes"
//    }
// ]

3.disconnect() method
By default, as long as the observed element is not garbage collected, the callback of MutationObserver will respond to the DOM change time and be executed. To prematurely terminate the execution callback, you can call the disconnect() method.
4. Reuse the MutationObserver() method
By calling the observe() method multiple times, you can reuse a MutationObserver object to observe multiple different target nodes.
5. Reuse the MutationObserver() method
Calling disconnect() does not end the life of the MutationObserver. You can reuse the observer and associate it with a new target node.

2.MutationObserverInit and observation range

1. Observation attribute
MutationObserver can observe the addition, removal and modification of node attributes. To register callbacks for attribute changes, you need to set the attributes attribute to true in the MutationObserverInit object.
The code is as follows (example):

let observer=new MutationObserver(
    (mutationRecords) => console.log(mutationRecords));
//Add attribute
//modify attribute
//Remove Attribute 
//It's all recorded

If you want to observe one or more attributes, you can use the attributeFilter attribute to set the whitelist, that is, an array of attribute name strings.
The code is as follows (example):

let observer=new MutationObserver(
    (mutationRecords) => console.log(mutationRecords));
//Add whitelist attribute
//Add excluded attributes
//Only foo attribute changes are recorded

If you want to save the original value of the attribute in the change record, you can set the attributeOldValue attribute to true.
The code is as follows (example):

let observer=new MutationObserver(
    (mutationRecords) => console.log(mutationRecords.map((x) => x.oldValue)));
//Each change retains the previous value

2. Observe character data
MutationObserver can observe the addition, deletion and modification of characters in text nodes. To register a callback for character data, you need to set the characterData property to true in the MutationObserverInit object.
3. Observe child nodes
The MutationObserver can observe the addition and removal of sub nodes of the target node. To observe child nodes, you need to set the childList property to true in the MutationObserverInit object.
4. Observe subtree
By default, the MutationObserver limits the scope of observation to the changes of an element and its child nodes. You can extend the scope of observation to the subtree of this element. You need to set the subtree attribute to true in the MutationObserverInit object.

3. Asynchronous callback and record queue

1. Record queue
Every time the MutationRecord is added to the record queue of the MutationObserver, the callback registered by the observer will be scheduled to the task queue as a micro task only if there is no scheduled micro task callback before.
2.takeRecords() method
Calling the takeRecords() method of the MutationObserver instance can empty the record queue, take out and return all the MutationRecord instances in it.

4. Performance, memory and garbage collection

The reference relationship between the MutationObserver instance and the target node is asymmetric. MutationObserver has a weak reference to the target node to be observed, so it does not prevent the garbage collector from collecting the target node. However, the target node has a strong reference to MutationObserver. If the target node is removed from the DOM and then garbage collected, the associated MutationObserver will also be garbage collected.


The document object model (DOM) is a language neutral API for HTML and XML documents. DOM Level 1 defines HTML and XML documents as a multi-level structure of nodes, and exposes JavaScript interfaces to manipulate the underlying structure and appearance of documents.
DOM consists of a series of node types, mainly including the following:
 Node is the base Node type, an abstract representation of a part of the document, and all other types inherit Node.
 the Document type represents the entire Document and corresponds to the root node of the tree structure. In JavaScript, a Document object is an instance of a Document and has many methods for querying and obtaining nodes.
 the Element node represents all HTML or XML elements in the document and can be used to manipulate their contents and attributes.
 other node types represent text content, comments, document types, CDATA blocks, and document fragments, respectively.
DOM programming is not a problem in most cases, and there is a little compatibility problem when it comes to < script > and < style > elements. Because these elements contain script and style information respectively, all browsers treat them differently from other elements.
The key to understanding DOM is to know the problems that affect its performance. DOM operation is expensive in JavaScript code, especially for NodeList objects. The NodeList object is "updated in real time", which means that a new query is executed every time it is accessed. Considering these problems, the number of DOM operations should be minimized in practice.
The MutationObserver is designed to replace the bad MutationEvent. It can be used to accurately monitor DOM changes, and the API is relatively simple.

Tags: Javascript

Posted on Sun, 21 Nov 2021 04:19:48 -0500 by no_maam