By Yin Ronghui @Tencent

Directory:

How is code parsed into DOM objects

How are node methods added to the DOM

3. Simply imitate the DOM mount method of the browser

Four, look at the JSDom source question

5. Understand element instantiation

You can also view this article on my Github and welcome Star. If you have any questions, please comment on Github.

How is code parsed into DOM objects

Take the following line of code as an example, to start exploring the process of code parsing, first put forward the first question, these three lines of code, how to parse into the DOM object?

<div id="exampleId">
    <span>hello world</span>
</div>
Copy the code

The DOM object looks like this:

You can click on the link to generate an AST in the screenshot to try modifying the HTML code to generate an abstract syntax tree. This is the first step for the browser to take the HTML code we wrote, because the format of the text is not easy to manipulate, such as the content of the exampleId attribute of a DIV node, you can think of using regular expressions, but you can’t live by regular expressions. There are a variety of attributes to fetch, as well as custom attributes to fetch, and the regular expression representation is no longer sufficient. Only when the content of the text is generated into a certain data structure can it be convenient to operate on it (such as the AST abstract syntax tree generated here). Such a similar document. HTML. Body. Div. Attrs. Id can take to succeed.

If you’re interested in the details of how browsers generate abstract syntax trees from HTML, it’s almost impossible to look at Chrome source code. You can check out a GitHub repository like this: Parse5, which is implemented in JS, is easy to view, and you can even view a regular expression version of the GitHub repository: HTML-parse-stringify, which uses regular expressions for everything I mentioned earlier

How are node methods added to the DOM

Solve the first problem, a simple abstract syntax tree, the next question again, the document we use at ordinary times. The getElementByTagName in our abstract syntax tree didn’t, we only have the attribute of simple HTML node nodeName, tagName, There are no such methods, so where do these methods of getting nodes come from?

Note: You can't view the Document properties from the Chrome console by typing document directly or using console.log(document). You need to use console.dir(document) to view its properties. The properties to view are as follows:Copy the code

After printing out the Browser’s Docuemnt object, we scroll down the prototype chain several levels until we find the getElementByTagName we’re looking for, which is mounted in a prototype chain like Document, as shown below. Why Document? How is it different from console.dir(Document)?


Here we need to bring out our W3C standard, why does the printed Document object have so many properties and such a long prototype chain? Because these are mandated by W3C standards, for example, a property field URL shown in the image above is what properties are required on a W3C Docuemnt, you can click here to see the defined properties, see here. As you can see, Document is an instance similar to Document. In fact, it’s just another layer of HTMLDocument between them.

In the W3C standard, you can see that it is implemented through interface inheritance. You can see the following in the standard:

interface Document : Node 
Copy the code

This means that Document inherits from the Node interface. So that’s where the prototype chain comes from, so let’s draw the prototype chain from the top to the bottom, and it looks something like this.

From this we can see that one Document is a W3C-defined interface and the other is an HTMLDocument instantiation.

Let’s take a look at the definition of each node in the prototype chain:

The definition of HTMLDocument interface The current standard: https://html.spec.whatwg.org/multipage/window-object.html#htmldocumentThe definition of MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLDocument Document interface The current standard: https://dom.spec.whatwg.org/#interface-documentThe definition of MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/Document Node interface The current standard: https://dom.spec.whatwg.org/#interface-nodeThe definition of MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/Node EventTarget interface The current standard: https://dom.spec.whatwg.org/#interface-eventtarget
MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget
Copy the code

3. Simply imitate the DOM mount method of the browser

After looking at these standards, you might want to see how browsers mount the various properties and methods defined in these standards onto the simple AST (Abstract syntax tree) we just generated with Parse5. Or said before, look at Chrome source code is not realistic, as a front-end engineer the best is to see if there is no JS implementation version, congratulations, found a JSDom, although the Chrome source code implementation mechanism can not be 100% similar, when the principle should be similar. Let’s take a look at how the getElementByTagName method is mounted to our AST.

The WHATWG interface definition is found here in JSDom, and is pretty much the same as what we see in the standard. Here is the definition file given in the JSDom. Let’s look at the implementation of JSDom:

As you can see, the general principle is to follow the W3C standards and mount the required methods into Prototype. This would be the case if we mounted it on the AST tree we generated

ASTTree.prototype.getElementsByTagName = function(tagName) {// The following code is only for general meaning and does not work properlyreturnthis.ASTTree.html.body.childNodes.forEach((child) => { child.tagName = tagName; })}Copy the code

If you want to get the corresponding node according to the TagName, you can easily use the getElementsByTagName that has been wrapped, and you have basically a prototype of our DOM tree.

Four, look at the JSDom source question

In fact, when you look at JSDom code and W3C standards, you may encounter some confusion, here I have encountered a few doubts take a long time to explain the two, to avoid you also step on the pit.

The first question is why console.dir(document) in Chrome DevTools has so many events, such as onauxclick, onblur, and onabort, that jsDOM doesn’t have in its document implementation.

It turns out that this is done by using mixins, which are also defined in the standard.

/ / in jsdom specific implementation mixins (DocumentImpl. Prototype, GlobalEventHandlersImpl. Prototype);Copy the code
// Document includes GlobalEventHandlers;Copy the code

Id,name, and style should all have nodeType. But why is there no nodeType?

I went to StackOverflow and got the following answer:

I tried it on the browser console and it is, as shown in the figure below, indicating that the attribute Attr is also a node, but based on the information found, this will be removed from the following standard and Attr will no longer be a node.

5. Understand element instantiation

This is just a rough idea of how the browser document instantiation works, and to strike while the iron is hot, take a look at instantiation of very similar elements. It doesn’t matter if you don’t know how to instantiate an element, just look at an example. Open DevTools, select a random node in the Element Tab, and then select the Properties Tab on the right to see the prototype chain of the Element instance.

HTMLDivElement

Each prototype chain node can be defined in w3c standards or MDN, and the implementation process is similar to adding methods to AST above, which can be found in JSDOM.

At this point, we’ve basically figured out why we normally write a text HTML code, and when a document object is available in the browser, there are a lot of things like onclick,getElementBy…. You can use. The innerHTML,outerHTML, and so on are available when a node is retrieved using getElementById. It’s all about creating an AST from code and then adding methods to the tree according to W3C standards to form your document, element and so on.

Finally, if you have any questions while reading this article or learning to explore the DOM, feel free to comment on Github or directly below. I’ll do it when I have time, and I’ll add it to the article when I get there.

Reference article:

How the browser renders HTML & CSS

An Introduction and Guide to the CSS Object Model (CSSOM)

Attributes and properties Provide location info for the attributes

Pointer Events

DOM