======================第一部分===================== ================================================
简述网页的渲染机制
一:为什么要了解浏览器渲染页面和加载页面机制,主要还是性能的优化。
了解浏览器如何进行加载,我们可以在引用外部样式文件,外部js时,将他们放到合适的位置,使浏览器以最快的速度将文件加载完毕。
了解浏览器如何进行解析,我们可以在构建DOM结构,组织css选择器时,选择最优的写法,提高浏览器的解析速率。
了解浏览器如何进行渲染,明白渲染的过程,我们在设置元素属性,编写js文件时,可以减少”重绘“”重新布局“的消耗。
这三个过程在实际进行的时候又不是完全独立,而是会有交叉。会造成一边加载,一边解析,一边渲染的工作现象。
二:用户访问网页都发生了什么。
用户访问网页,DNS服务器(域名解析系统)会根据用户提供的域名查找对应的IP地址,找到后,系统会向对应IP地址的网络服务器发送一个http请求。网络服务器解析请求,并发送请求给数据库服务器。数据库服务器将请求的资源返回给网络服务器,网络服务器解析数据,并生成html文件,放入http response中,返回给浏览器。浏览器解析 http response。浏览器解析 http response后,需要下载html文件,以及html文件内包含的外部引用文件,及文件内涉及的图片或者多媒体文件。(这里进入主题了也就是下面的第三大点)
1~4步骤HTTP协议的一些内容,访问服务器端可能遭遇的问题:如果网络服务器无法获取数据库服务器返回的资源文件(http response 404),或者由于并发原因暂时无法处理用户的http请求(http response 500)。
三:浏览器渲染页面和解析加载页面机制。
a.加载,即为获取资源文件的过程,不同浏览器,以及他们的不同版本在实现这一过程时,会有不同的实现效果(资源间互相阻塞,可以用timeline来做测试)。这里先说下浏览器的5个常驻线程:
- 浏览器GUI渲染线程
- javascript引擎线程
- 浏览器定时器触发线程(setTimeout)
- 浏览器事件触发线程
- 浏览器http异步请求线程(.jpg 这类请求)
备注:现代浏览器存在 prefetch 优化,浏览器会另外开启线程,提前下载js、css文件,需要注意的是,预加载js并不会改变dom结构,他将这个工作留给主加载。
注意:这里也涉及到 阻塞 的现象,当js引擎线程(第二个)进行时,会挂起其他一切线程,这个时候3、4、5这三类线程也会产生不同的异步事件,由于 javascript引擎线程为单线程,所以代码都是先压到队列,采用先进先出的方式运行,事件处理函数,timer函数也会压在队列中,不断的从队头取出事件,这就叫:javascript-event-loop。简单点说应该是当在进行第二线程的时候,1,3,4,5都会挂起,比如这时候触发click事件,即使先前JS已经加载完成,click事件会压在队列里,这里也要先完成第二线程才会执行click事件。
加载顺序:
浏览器解析http response 下载html文件会”自上而下“加载,并在加载过程中进行解析渲染。“自上而下”加载时遇到图片、视频之类资源时便会进入第5个线程,这是异步请求,并不会影响html文档进行加载。
加载过程中遇到外部css文件,浏览器另外发出一个请求,来获取css文件。这里也是第5个线程,这里css解析会生成一个rule tree(规则树),这个以后会更新。当文档加载过程中遇到js文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。
原因:JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。办法:可以将外部引用的js文件放在前。
4. css可能影响js的执行造成阻塞。
原因:如js里面var width = $('#id').width();这里js执行前,浏览器必须保证之前的css文件已下载和解析完成(后面的不会影响),这也是css阻塞后续js的根本原因。当js文件不需要依赖css文件时,可以将js文件放在头部css的前面。
5. 预加载网页,利用空余时间来提前加载该网页的后续网页。
<link rel="prefetch" href="http://">
6. 为js脚本添加defer属性,其不会阻塞后续DOM的的渲染。但是因为这个defer只是IE专用,所以一般用得比较少。而我们标准的的HTML5也加入了一个异步载入javascript的属性:async,无论你对它赋什么样的值,只要它出现,它就开始异步加载js文件。但是, async的异步加载会有一个比较严重的问题,那就是它忠实地践行着“载入后马上执行”这条军规,所以,虽然它并不阻塞页面的渲染,但是你也无法控制他执行的次序和时机。
<script defer="true" src="JavaScript.js" type="text/javascript"/>
渲染过程
解析 HTML 标签, 构建 DOM 树
解析 CSS 标签, 构建 CSSOM 树
把 DOM 和 CSSOM 组合成 渲染树 (render tree)
在渲染树的基础上进行布局, 计算每个节点的几何结构
把每个节点绘制到屏幕上 (painting)
CSS和JS在网页中的放置顺序是怎样的?
css放在head中
js放在的前面
解释白屏和FOUC(渲染机制不同)
白屏:如果把样式放在底部,对于IE浏览器,在某些场景下(新窗口打开,刷新等)页面会出现白屏,而不是内容逐步展现(css加载太慢无法构建cssom树,渲染要在构建基础上才能进行)
如果使用 @import
标签,即使 CSS 放入 link, 并且放在头部,也可能出现白屏
FOUC:如果把样式放在底部,对于IE浏览器,在某些场景下(点击链接,输入URL,使用书签进入等),会出现 FOUC 现象(逐步加载无样式的内容,等CSS加载后页面突然展现样式).对于 Firefox 会一直表现出 FOUC .
async和defer的作用是什么?有什么区别
没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script async src="script.js"></script>
有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
<script defer src="script.js"></script>
有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。
defer:脚本延迟到文档解析和显示后执行,有顺序
async:不保证顺序
======================第二部分===================== ================================================
JavaScript 定义了几种数据类型? 哪些是简单类型?哪些是复杂类型?
- 数值(number):整数和小数(比如1和3.14)
- 字符串(string):字符组成的文本(比如"Hello World")
- 布尔值(boolean):true(真)和false(假)两个特定值
- undefined:表示“未定义”或不存在,即此处目前没有任何值
- null:表示空缺,即此处应该有一个值,但目前为空
- 对象(object):各种值组成的集合
其中,对象又可以分成三个子类型。- 狭义的对象(object)
- 数组(array)
- 函数(function)
1,2,3,4,5是简单类型;6为复杂类型
NaN、undefined、null分别代表什么?
NaN:表示Not a Number,NaN和任何值都不相等,包括自己,但它属于Number类型
undefined:如果只是声明变量而没有赋值,则该变量的值是undefined。
是一个JavaScript关键字,表示“无定义”。
null:null表示”没有对象”,即该处不应该有值。
typeof和instanceof的作用和区别?
instanceof
此运算符可以判断一个变量是否是某个对象(类)的实例,返回值是布尔类型的typeof
此运算符可以返回一个字符串,用语说明元算数的类型,它的返回值"number"
typeof a;
typeof "123"
a instanceof Object
"123" instanceof Object
版权归本人和饥人谷所有,转载请注明出处