1. 说说JS的事件循环或者event loop
JS是单线程的,为了防止代码阻塞,把任务分成同步任务和异步任务。
同步任务放入JS引擎直接执行,原地等待结果,其任务放入执行栈;而异步任务需要放入宿主环境(浏览器、Node),不用原地等待结果,比较耗时,其任务放在任务队列中。
首先执行同步任务,将其放入执行栈中执行,当执行栈中的任务执行完毕后,会去看任务队列中是否有任务需要执行,有的话将其放入执行栈中执行,执行完毕后再去看任务队列中是否还有任务,有的话再放入执行栈,如此循环,称为事件循环机制。
2. 实战题:同步任务、宏任务、微任务,写出输出先后顺序(事件轮询机制)
3. 说说对跨域的理解,如何解决呢?
跨域是浏览器会对当前页面发起的与当前协议、域名、端口号不同的请求,进行拦截。(也就是请求资源的地址和目标资源的地址不一致时,浏览器出于安全考虑,会限制两个源的资源交互)。
解决方法:
(1) CORS(Cross-source resource sharing,跨域资源共享),通过在服务器端设Access-Control-Allow-Origin响应头为*,就是允许所有域名访问;或者改为请求资源的地址即可
(2)JSONP:
利用script 属性的 src 不会跨域,可以通过拼接 src 向服务端发起 GET 请求。
怎样使用返回的数据? 通过 query 参数指定回调函数,来完成数据的回调。
(3)代理服务器:
在同域下设置一个代理服务器,由代理服务器向目标服务器发送请求,然后将结果返回给前端。这样在浏览器看来,所有请求都是同域的。
4. 说说浏览器的事件模型,冒泡和捕获的区别?
事件有两个阶段,捕获和冒泡。
事件捕获(capture): 浏览器从最外层的元素wrapper开始,向内层元素normal传递事件,直到目标元素child。在这个过程中,浏览器会依次触发wrapper元素和normal元素的捕获阶段事件处理函数。
事件冒泡(bubble): 当事件处理完成后,浏览器会从目标元素child开始,向外层元素normal和wrapper传递事件,直到最外层的元素。在这个过程中,浏览器会依次触发normal元素和wrapper元素的冒泡阶段事件处理函数。
5. 如何判断当前触发事件的元素,currentTarget 和 target 有什么区别?
target 指向真正触发事件的子元素,即事件发生的源头,currentTarget 指向当前元素,事件处理程序附加到的元素。
6. addEventListener 的第三个参数有什么作用?
表示冒泡或者捕获阶段,true代表捕获阶段,false代表冒泡阶段,默认冒泡阶段
7. 说说事件代理(delegation),有什么用,解决了什么问题?
由于事件冒泡和事件捕获,父元素能够感知到子元素的事件。
如果子元素很多,绑定起来内存消耗较大,可以将事件绑定在父元素上,这种方法就叫做事件委托或者事件代理。
通过 e.target 即可获取真正触发事件的子元素
8. localStorage 和 sessionStorage 的区别是什么?还知道哪些存储方案,有什么缺点和不同?
区别:localStorage跟网站绑定,公用一个,不会因为页面关闭而丢失数据;而sessionStorage跟当前页面绑定,页面销毁,就会消失。
(1)cookie:为了解决HTTP协议的无状态问题(也就是每次访问服务器关闭后再次访问,不能意识到是同一用户),一种每次HTTP请求自动带数据的技术。兼容性好。
更多应用于鉴权等信息传递,一般通过服务器返回set-cookie的响应头来进行设置。
cookie本身会在访问服务器时自动携带,每个cookie会有一个domain参数,domain就是设置的域名,如果设置的域名与服务器的域名相同会自动携带。所以一般把登录信息放在cookie里面,它会自动携带。
但是只能存储少量数据,且打开浏览器就能看到很不安全
(2)localstorage:本地存储,永久存储,数据不受页面刷新、关闭的影响(常用)
(3)sessionstroage:会话存储,页面关闭数据清空
(4)indexDB:类似SQL数据库存储,但存储的是对象。相比传统的浏览器存储方式(如 Cookie 或 LocalStorage),IndexedDB 能够存储更大量的数据。
9. http 缓存有了解吗?对于 html 文件,css,js 文件,该怎么缓存呢?有什么说法
http分为强缓存和协商缓存。
强缓存: 依赖浏览器的本地缓存机制,在缓存有效期内直接从本地获取资源,不向服务器发送请求。
控制强制缓存的字段分别是Expires 和 Cache-Control ,其中Cache-Control优先级比Expires高。Expires缺点在于返回一个绝对时间(时间戳)。因为Expires参照的是本地客户端的时间,而客户端的时间是可以被修改的,所以会有误差产生的情况,这也是Expires的一个缺点,所以有了后来Http1.1规范的Cache-control。Cache-Control本质是相对时间,单位是秒,代表缓存时间。
另外,Cache-control的优先级要高于Expires,如果两者同时设置,会优先使用Cache-control而忽略掉Expires。
如果通过返回200状态码,不用请求服务器,直接从本地获取资源。
协商缓存: 是浏览器本地每次都向服务器发起请求,由服务器来告诉浏览器是从缓存里拿资源还是返回最新资源给浏览器使用。
涉及到一对响应头Last-Modified
(绝对时间)和 请求头 If-Modified-Since
,第一次访问服务端会返回Last-Modified,第二次访问浏览器会带上If-Modified-Since,然后服务端会对比这两个头是否发生变化,变化了不会命中协商缓存。last-modified 缺点,服务器时间和客户端时间不一致,故 http 1.1 引入了 Etag。
响应头 Etag(
本质上对文件内容做了一次哈希,一个字符串,当文件内容改变这个值就会发生变化) & 请求头 If-None-Match
。浏览器初次请求资源,服务器返回Etag值携带在响应头里返回给浏览器,当浏览器再次请求资源时会在请求头里携带If-None-Match,值是之前服务器返回的Etag的值,服务器收到之后拿该值与资源文件最新的Etag值做对比。
如果没有变化则返回304命中协商缓存,告诉浏览器继续使用缓存(不返回资源文件)。
如果发生变化,则返回200和最新的资源文件给浏览器使用。
html 文件不缓存或协商缓存,html 中会引入不同 hash 的 js 和 css,每次发布都会更改
css,js 文件,使用强缓存。因为打包工具会自动增加一个 hash 在 css 和 js 上,比如 index.645bagfh.js,所以每次更新后地址会直接变化。
图片使用强缓存
10. html 是如何渲染的?
对html进行解析,构建DOM树和CSS规则树,组合生成render树,布局渲染最终展示到用户面前。
11. async 和 defer 的区别是什么?平时用哪个?
(1) 没有 defer 和 async:加载和执行,都会阻塞 html 的解析
(2) defer 属性的 js:按顺序加载和执行,且都不会阻塞 html 的解析,会在解析完成后,按顺序执行
(3) async 属性的 js: 异步加载和执行,不会阻塞 html 解析,并行下载,下载完就执行,没有顺序
用defer多:
使用 defer 进行优化,不阻塞 html 解析;执行会按照顺序来,保证了正确性。