1、解析规定:

1、html字符串被浏览器接管后一句一句读取并解析
2、如果解析到link标签,便发送申请获取css;
3、解析到script标签,发送申请获取js后并执行相应的代码
4、解析到img后会申请图片资源
5、在解析html过程中构建dom树,解析css等过程中构建渲染树,递归布局后进行页面绘制

2、开始解析html

//解析器通常会把工作调配给两个组件:分词程序负责把输出的html切分成非法的序列;解析程序依照句法规定去剖析而后构建句法树。
<html>

<body>    <p>hello taya</p>    <div><p>hiiiiii</p></div></body>

</html>
1
2
3
4
5
6
7
该html解析成DOM树后为:

HTMLHtmlElement
HTMLBodyElement
HTMLParagraphElement
Text
HTMLDivElement
HTMLParagraphElement
Text
3、css选择器的读取程序是从右向左、选择器性能解释

taya div.ty span{ color:red }

1
它的读取程序是:span => div class:ty => id:taya
先找到全局的span,而后从第一个开始向上寻找class为ty的div,而后再寻找id为taya的元素,如果没有匹配项则放弃本条门路,从下一个span开始寻找。
如果是自左向右,便变成了深度遍历并随同着大量的回溯节点,十分耗费性能
这也是为什么在性能方面:id选择器 > 类选择器 > 元素选择器

4、js解析

1、js是单线程,只能依照先后顺序执行
2、浏览器解析是异步的,当须要申请内部资源时是不会影响html加载的,然而如果遇到js文件,则会将解析挂起,因为js中可能会有针对DOM的操作(js优化咱们须要尽可能地去防止)
3、js解析器会先进行预解析,即找到所有的变量、函数等进行初始化赋值为undefined,把函数取出来成为一个函数块,寄存到仓库中,而后再解析js代码,和仓库进行匹配

依据以上的机制,能解释很多词法作用域的问题:

1:
console.log(a)
let a = 1
console.log(a)
//后果: undefined 1

2: //如果应用let,这个例子就没有用了,会报错。
console.log(taya) //function taya(){console.log("4")}
var taya = "sdsd"
console.log(taya) //sdsd
function taya(){console.log("11")}
console.log(taya) //sdsd
var taya = "3"
console.log(taya) //3
function taya(){console.log("4")}
console.log(taya) //3
解析:在js预解析时,如果变量和函数重名,只会保留函数块,所以第一个taya输入为函数
在解析时,只有+ - * / % =等字符时能力更改仓库中的值,所以后续的taya输入不为函数了

3:
var a = 1;
function fc(){

console.log(a)a = 2

}
fc()
console.log(a)
输入:1 2
解析:执行fc()函数时,发现外部并没有定义任何变量,第一行输入a,仓库内是空的,便向内部寻找,找到了全局变量a。

4:
var a = 1;
function fc(a){

console.log(a)a = 2

}
fc(1)
console.log(a)
//输入:1 1