一、html的<script>标签上的async属性和defer属性的作用与区别。
几个基本知识点:1. 在浏览器渲染页面和执行js脚本的过程当中,为了不至于页面渲染的紊乱,GUI渲染线程和JS执行线程是互斥的,不能同时执行。 2. 浏览器读取html标签和渲染的顺序始终是从上到下顺序执行的。3. 页面引用的js脚本下载和执行分别是I/O线程和JS执行线程处理。
-
如果script标签上没有async属性和defer属性,当读取到script标签时,GUI线程会被挂起,然后启用I/O线程下载脚本并尽快执行,执行完毕后继续渲染后面的页面。
-
如果script标签上存在async属性,当读取到script标签时,GUI线程继续渲染页面同时启用I/O线程下载脚本,当脚本下载完毕时,尽快挂起GUI线程,启用JS执行线程执行脚本。
-
如果script标签上存在defer属性,当读取到script标签时,GUI线程继续渲染页面同时启用I/O线程下载脚本,当脚本下载完毕时继续等待GUI线程渲染剩下的页面。直到页面渲染完毕,启用JS执行线程执行脚本。
所以不管是async还是defer,所谓的异步都是指脚本的下载和页面的渲染可以并行。因为单线程以及执行线程和渲染线程互斥的缘故,脚本的执行和页面渲染,以及两个脚本之间的执行都不是并行的。async和defer的区别是,执行脚本的时机不同,async是下载完尽快挂起渲染线程然后启动JS执行线程执行,defer是下载完还是需要等到页面渲染完成,触发 DOMContentLoaded事件前执行。
二、简述一下require.js实现前端模块化AMD规范的思路和方法。
- 提供给全局两个方法,其中define用于定义模块,require用于引用模块。
- define定义的模块和require引入的模块如果不依赖任何模块,那很简单,define相当于把模块根据id存起来,require用相同的id取出并执行。
- define和require解决依赖模块的方法,创建script标签加载异步模块,监听模块load完成执行模块,然后递归用同样的方法处理其依赖的模块。最后把依赖模块都执行完之后,作为参数传给callback。
- 与CMD规范的区别是,AMD规范需要始终先将所有依赖的模块加载并执行完。CMD只是先加载,只有在需要的时候才执行模块并获得其返回。
三、列举几个浏览器渲染进程中的几个线程以及它们的作用。
- GUI渲染线程
- 负责渲染浏览器页面,解析Html、css,构建DOM树以及RenderObject树,负责布局和绘制等。
- GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起,GUI的更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
- JS引擎线程
- JS引擎线程负责解析和执行所有的JavaScript代码。一个Tab页中永远只有一个线程在运行JS代码。
- 由于GUI渲染线程和JS引擎线程是互斥的,所以如果JS执行时间过长,这样会造成页面的渲染不连贯,导致页面渲染加载阻塞。这就是为什么我们需要在前端分包,异步加载脚本以及脚本中应当避免计算量过大任务并将其分成多个小任务放到事件队列中。
- 事件触发线程。
- 用来控制事件循环。
- 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
- 注意,由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)
- 定时触发线程、异步http请求线程
- 定时触发线程负责setInterval、setTimeout的计时并触发定时,将回调调放入事件队列中,等待JS引擎空闲时执行;
- http请求是浏览器打开一个新的线程请求,当请求回调时将回调放入事件队列中,等待JS引擎空闲时执行。
四、简述一下Cookie和Session。
由于Cookie的实现机制,一旦服务器端向客户端发送了设置Cookie的意图后,除非Cookie过期,否则每次客户端请求都会发送这些Cookie到服务器端,一旦设置的Cookie较多,请求报头就会过大而且不是每一个请求都会用上这些Cookie,所以造成了带宽的浪费。
- 如果可能,尽量减少Cookie的大小。
- 为静态组件使用不同的域名。
简而言之就是,为不需要Cookie的组件换个域名可以实现减少无效Cookie的传输。所以很多 网站的静态文件会有特别的域名,使得业务相关的Cookie不再影响静态资源。当然换用额外的域 名带来的好处不只这点,还可以突破浏览器下载线程数量的限制,因为域名不同,可以将下载线 程数翻倍。但是换用额外域名还是有一定的缺点的,那就是将域名转换为IP需要进行DNS查询, 多一个域名就多一次DNS查询。
- cookie容易被篡改。
Cookie除了可以通过后端添加协议头的字段设置外,在前端浏览器中也可以通过JavaScript 进行修改,浏览器将Cookie通过document.cookie暴露给了JavaScript。前端在修改Cookie之后,后续的网络请求中就会携带上修改过后的值。
Session是一种将数据保存在服务器端的用户状态机制。依赖Cookie或者查询字符串来与客户端建立对应关系。