面试一

标签语义化

【谈谈你对标签语义化的认识?】

常见的语义化标签:

<header></header>头部
<nav></nav>导航栏
<section></section>区块(有语义化的div)
<main></main>主要区域
<article></article>主要内容
<aside></aside>侧边栏
<footer></footer>底部

为什么要用语义化标签:

  • 可以使文档结构更加清楚(文档结构)
  • 可以让浏览器更好的读取页面结构(浏览器)
  • 语义化更具可读性,有利于团队开发和维护(开发团队)

浏览器渲染机制

相关概念

DOM: DOM Object Model,浏览器将HTML解析成树形的数据结构

CSSOM:CSS Object Model,浏览器将css解析成树形的数据结构

Render Tree:DOM和CSSOM合并后生成的渲染树

Render树和DOM一样,以多叉树的形式保存了每个节点的css属性、节点自身属性、以及节点的孩子节点。

注意:display:none的节点不会被加入Render Tree,而visibility:hidden则会,所以如果某个节点最开始是不显示的,则设置为后者更优

Layout: 有了render tree我们就可以知道网页中有哪些节点、各个节点的css定义以及他们的从属关系。而下一步之所以成为layout(即布局的意思)就是计算出每个节点在屏幕中的位置

Panting:Layout后浏览器已经知道了哪些节点要显示,每个节点的css属性是什么,以及节点在屏幕中的位置在哪里。这就进入了最后一步:Panting,按照上面计算的结果,通过显卡,把内容画到屏幕上

Repaint:即重绘,改变某个元素的背景色,文字颜色、边框颜色等,屏幕的一部分要重绘,但是元素的集合尺寸没有变化

不影响它周围或内部布局的属性

Reflow:回流:元素的集合尺寸发生变化,需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化

reflow几乎是无法避免的。现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显 示与隐藏)等,都将引起浏览器的reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引起它内部、周围甚至整个页面的重新渲 染。通常我们都无法预估浏览器到底会 reflow哪一部分的代码,它们都彼此相互影响着。

display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。

DOM和CSSOM的构建流程

在这里插入图片描述

【DOM和CSSOM构建的详细过程:】

1、 当服务器返回一个HTML文件给浏览器的时候,浏览器接受到的是一些字节数据。

2、 然后浏览器根据HTTP响应中的编码方式(通过是UTF8),解析字节数据,得到一些字符。如果这个时候编码方式跟文件的字节编码不一致,便会出现乱码。所以我们通过使用<meta http-equiv="content-type"content=“text/html;charset=utf-8”>来告诉浏览器我们页面使用的是什么编码。

3、 这个时候,浏览器再根据DTD中的对元素(标签)的定义,对这些接受到的字符进行语义化(token)。我们经常在html文件的第一行,定义,这个DTD就是告诉浏览器,那些字符是有意义的,那些字符是无意义的。DTD常见的有严格、过渡、框架和HTML5三种。不同的DTD中,有不同的元素定义。比如过渡的DTD中就比严格的DTD中多出了

、 等等一些元素的定义,也就是说使用严格的DTD,即使你在你的HTML文件中使用了
,浏览器也会忽略掉的。所以也就有了一些人使用不同的DTD或者不使用DTD的时候,布局会明显不同的原因了。

4、 接着,浏览器再使用这些语义块(token)创建对象,形成一个个节点了。

5、 然后HTML解析器就会从HTML文件的头部到尾部,一个个地遍历这些节点。当这些节点是普通节点的话,HTML解析器就会将这些节点加入到DOM树中。当这些节点是JS代码的话,HTML解析器就会将控制权交给JS解析器。如果这些节点是CSS代码的话,HTML解析器就会将控制权交给CSS解析器。不过,当外联的JS代码和CSS代码还没从服务器传到浏览器的时候,这个时候如果DOM树上有可视元素的话,浏览器通常会选择在这个时候,将一些内容提前渲染到屏幕上来。

6、 当HTML解析器读到最后一个节点的时候,整个DOM树也构建完成了,这个时候就会触发domContentloaded事件。而很多JS库(像JQ)通常会在这个时候有所反应的。

至此,DOM树就全部构建完成了。

加载资源

当浏览器获得HTML文件后,就会自上而下的去加载资源,并在加载的过程中解析和渲染

这里的加载就是指的获取资源文件的过程

  • 加载过程中遇到外部css文件和图片:浏览器会另外发送一个请求,去获取css文件和图片(这个请求是异步的,不会影响html文件的加载)
  • 加载遇到js文件,html会挂起渲染的进程,等待js文件加载完毕后,再继续进行渲染

【为什么html要等待js呢?】

因为js可能会修改dom,导致后续的html资源白加载,所以html必须要等待js文件加载完毕后,在继续进行渲染,这也就是为什么js文件写在底部body标签前的原因了

浏览器的渲染流程

在这里插入图片描述

【DTD文档声明格式】

由于html有很多个版本的规范,每个版本的规范之间有一定的差异,所以为了让浏览器能够正确的编译/解析渲染我们的网页,我们需要再html文件的第一行告诉浏览器我们的网页是用哪个版本写的(每一个不同的版本的规范都有不用的DTD文档声明),浏览器知道后,它就能够正确的编译/解析/渲染我们的网页

浏览器的各个进程及其作用:参考链接
【要知道的:浏览器包含的主要进程】

Browser进程(浏览器主进程)

浏览器渲染进程(浏览器内核/Render进程)

第三方插件进程

GPU进程

【浏览器渲染进程所包含的线程:】

GUI渲染线程

JS引擎线程

事件触发线程

定时器触发线程

异步http请求线程

【浏览器的渲染流程:】

  1. 在浏览器输入url时,浏览器主进程开启一个下载进程,然后根据用户的请求获取的页面相关数据

  2. 将响应的数据通过渲染主机接口转交给渲染进程

  3. 浏览器渲染进程接收到消息后,对其进行简单解释后,会交给渲染线程GUI,然后开始渲染

  4. GUI渲染线程接收到请求后,解析HTML、CSS文件并构建对应的DOM树,css规则树最终将他们合并成渲染树。通过对渲染树进行相关布局,对渲染树进行绘制

  5. 最后浏览器渲染进程将绘制的结果传递给浏览器主进程

  6. 浏览器主进程接收到结果,并将结果以页面的形式显示出来

    这里浏览器主进程会将默认图层和复合图层交给GPU进程,GPU进程在将各个图层合成,最后显示出页面

浏览器

浏览器的多进程

浏览器是多进程的,一个tab页对应一个进程。

浏览器也有自己的优化机制,同一类型的标签页会合并到一个进程,不同类型的标签页会开启一个进程

下面是浏览器浏览器包含的一些主要的进程:

在这里插入图片描述

【浏览器多进程的优势】:

1、避免单个page crash影响整个浏览器
2、避免第三方插件crash影响整个浏览器
3、多进程充分利用多核优势
4、方便使用沙盒模型隔离插件等进程,提高浏览器稳定性

浏览器渲染进程的多线程

浏览器是多进程的,浏览器的渲染进程是多线程的

浏览器渲染进程即浏览器内核,是浏览器的进程之一:主要作用:进行页面的渲染、脚本执行、事件处理等

浏览器渲染进程会开启多个线程协作完成,包括:GUI渲染线程,JS引擎线程,事件触发线程,定时器触发线程,异步HTTP请求线程。主要的线程以及作用如下:

查看CSDN上的详细内容

浏览器主进程和渲染进程的通信

还未看到

js运行机制

js的运行(执行)机制就是事件循环

js(引擎)是单线程

JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题(譬如多线程操作一般要加锁)。

比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

任务队列

【要知道的:】

上面我们已经知道JS引擎是单线程,任务应该是按顺序执行的,那么怎么会有同步异步之说?

  • 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
  • 如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。
  • JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

【结论】

所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。

  • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  • 异步任务指的是,不进入主线程、而进入**“任务队列”**(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

js的事件轮询机制

  1. 所有同步任务都在主线程(即js引擎线程)上执行,形成一个执行栈
  2. 而异步任务均由事件触发线程控制,其有一个任务队列。只要异步任务有了运行结果,就在"任务队列"之中放置回调事件
  3. 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",按顺序结束等待状态,进入执行栈,开始执行。
  4. 线程不断重复上面的第三步
  5. 只要主线程空了,就会去读取"任务队列",这个过程会不断重复。这就是JavaScript的运行机制。又称为Event Loop(事件循环或者轮询)。

事件队列是js事件触发线程里面的一个队列。事件触发线程的一个作用就是控制事件循环

在这里插入图片描述

只要异步任务有了运行结果,就在“任务队列”之中放置一个事件。

也就是说每个异步任务准备好了就会立一个唯一的flag,这个flag用来标识对应的异步任务。

“任务队列”是一个事件的队列(也可以理解成是消息的队列)

“任务队列”中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入“任务队列”,等待主线程读取。

“任务队列”是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。

>主线程的读取过程基本上是自动的,只要执行栈一清空,“任务队列”上第一位的事件就自动进入主线程。但是,如果包含“定时器”,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

任务队列中的事件:IO设备、用户产生事件、定时器事件、Promise

在这里插入图片描述

当一个任务被执行,js会判断是否为同步任务,如果是同步,压入主线程立即执行;但如果是异步任务,移到异步处理模块(Task Table),当异步任务有了结果,就将异步任务的回调函数注入到任务队列中等待

宏任务和微任务

异步任务中又分为宏任务与微任务两种,当执行栈为空,每次准备取出第一个宏任务之前都要先将所有的微任务一个一个取出执行

macro-task(宏任务):

定时器回到、Dom回调、ajax回调

micro-task(微任务):

Promise里面的then回调,process.nextTick,MutaionObserver

定时器的注意点

setTimeout(() => console.log('我第一'), 3000);

站在宏观思想上理解,这行代码的意思是这个定时器将在三秒后触发,但站在微观的角度上,3000ms并不代表执行时间,而是将回调函数加入任务队列的时间,这也是为何存在定时器执行与所设置等待时间不符的问题所在。

浏览器的工作原理

主流浏览器及其内核

goole => Webkit(以前) => Blink(现在)

ie => Trident

firefox => Gecko

safari => 是Webkit

opera => 之前Presto,后来加入谷歌从Webkit又到了Blink

第一部分:网络通信

CSDN参考:网络通信参考
完整的网址 =》统一资源定位符(URL)=》协议名+服务器名+域名

http://www.baidu.com

协议名: http

服务器名:www

域名:baidu.com

域名解析

域名解析(主机名解析):DNS最终通过我们输入网址的主机名/服务器名,找到该网址唯一对应的IP地址

运行上的ip地址:163.177.151.109

DNS(Domain Name System)会为我们解析域名

万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住那一长串能够被机器直接读取的IP数串

DNS进行域名解析之前

  1. 会先搜索自身的DNS缓存(如果找不到自身的缓存)
  2. 开始搜索操作系统的DNS缓存,如果找到了缓存并且缓存没有过期就停止搜索和解析(如果操作系统也找不到缓存)
  3. 尝试读取位于C:\Windows\System32\drivers\etc目录下的hosts文件,查看文件里面有没有该域名对应的IP地址,如果有则解析成功。(如果hosts文件还找不到对应的条目)
  4. 浏览器会向本地配置首选的运营商DNS服务器发起域名解析请求(如果运营商的DNS服务器也搜索不到自身所对应的DNS缓存)
  5. 运营商DNS服务器就会代我们的浏览器向根域的DNS发起请求
  6. 根域首先会替我们解析顶级域名(.com),返回顶级域名.com的ip地址。
  7. 运营商的DNS接着向顶级域名.com的ip地址发起请求,顶级域名.com再返回baidu.com域名的ip地址
  8. 运营商DNS服务器又会向baidu.com域名的ip地址(二级域名服务器)发起请求查找www.baidu.com的ip地址,这时baidu.com域名的DNS服务器通过主机名www找到www.baidu.com的ip地址并返回给运营商的DNS服务器。
  9. 运营商的DNS服务器接着把最终的ip地址返回给我们的Windows操作系统内核,操作系统内核又把结果返回给浏览器,于是到此浏览器终于得到了www.baidu.com这个网站名的ip地址,解析成功。

浏览器输入网址(URL) =>DNS解析URL => 向目标网站发送请求

解析完URL获得对应的ip地址后,浏览器会遵循超文本传输协议http的规范(现在更多采用https协议,因为https更加安全可靠),向目标网站服务器发起请求。浏览器根据TCP/IP网络协议,利用我们所拿到的ip地址与目标网站服务器建立通信。

TCP/IP

TCP是一种面向连接的传输层控制协议,在发送数据前,通信双方必须在彼此间建立一条连接,客户端和服务器端的内存里分别保存一份于对方的信息,如ip地址、端口号等。

TCP可以看成是一种字节流,该协议提供了一种可靠的面向连接服务,采用三次握手建立一个连接,采用四次挥手来关闭一个连接。

三次握手

参考一:三次握手

参考二:三次握手

目的:确认两台主机都具备接收和发送信息的能力

*第一次握手让服务器主机B知道客户端主机A可以发出消息*

请求建立连接:SYN=1

发送序列号:seq=n,其中n为一个数。

*第二次握手让客户端主机A知道了服务器主机B能接收到信息,也能发出信息。*

同意建立连接(SYN = 1)

确认收到了刚才的信息(ack = 刚才的seq + 1)

发出自己的序列号(seq = x,其中x为一个数)。==>让客户端主机A回复这个数加一才能确认客户端主机A也能接收到消息

*第三次握手让B知道了A能接收到。*

现在开始发送(SYN = 0)

成功收到了服务器主机B的信息(ack=刚才的seq + 1)

发送序列号:seq=最开始发出的序号 + 1

通过TCP三次握手建立了TCP/IP连接后,浏览器会向服务器主机发起一个HTTP-GET方法报文请求。请求中包含访问的URL,也就是 http://www.baidu.com/ ,还有浏览器操作系统信息、编码等。

服务器端接收到http请求以后,便会响应和处理该http请求,处理之后给浏览器返回html文件。(接下来就是将拿到的html文件进行渲染)

四次挥手

参考一:四次握手参考

参考二:四次握手参考

第二部分:页面渲染

执行上下文

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值