前端面试宝典二(浏览器篇)

1、同源策略及解决跨域常用的方法

因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,Ajax 请求会失败。

我们可以通过以下几种常用方法解决跨域的问题

JSONP
JSONP 的原理很简单,就是利用 <script> 标签没有跨域限制的漏洞。通过 <script> 标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时
JSONP 使用简单且兼容性不错,但是只限于 get 请求。
CORS
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。
服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
document.domain
该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。
只需要给页面添加 document.domain = 'test.com' 表示二级域名都相同就可以实现跨域
postMessage
这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息
nginx反向代理

2、事件机制(冒泡,捕获,事件委托)

事件触发有三个阶段

  • window 往事件触发处传播,遇到注册的捕获事件会触发
  • 传播到事件触发处时触发注册的事件
  • 从事件触发处往 window 传播,遇到注册的冒泡事件会触发

事件触发一般来说会按照上面的顺序进行,但是也有特例,如果给一个目标节点同时注册冒泡和捕获事件,事件触发会按照注册的顺序执行

1)事件冒泡:从事件源朝父级一直到根元素(HTML)。当某个元素的某类型事件被触发时,那 么它的父元素同类型的事件也会被触发,
一直触发到根源上;从具体的元素到不确定的元素.
2)事件捕获:从根元素(HTML)到事件源,当某个元素的某类型事件被触发时,先触发根元素 的同类型事件,朝子一级触发,
一直触发到事件源。从不确定的元素到具体的元素;
3) 事件委托:利用事件冒泡的原理,子元素的事件会冒泡到父元素,可以只给父元素添加事件, 通过事件目标判断元素。
优点:节省内存,动态添加的子元素也包含事件
4) 阻止冒泡
标准的W3C方式:e.stopPropagation()
非标准的IE方式:window.event.cancelBubble=true

3、js事件循环机制(Event Loop)

js是一门单线程的预言,在js中,任务分为宏任务(macrotask)和微任务(microtask),这两个任务分别维护一个队列,均采用先进先出的策略进行执行!同步执行的任务都在宏任务上执行。
宏任务主要有:script(整体代码)、setTimeout、setInterval、I/O、UI 交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)。
微任务主要有:Promise.then、 MutationObserver、 process.nextTick(Node.js 环境)。
具体的执行步骤如下:

  1. 从宏任务的头部取出一个任务执行;
  2. 执行过程中若遇到微任务则将其添加到微任务的队列中;
  3. 宏任务执行完毕后,微任务的队列中是否存在任务,若存在,则挨个儿出去执行,直到执行完毕;
  4. GUI 渲染;

然后回到步骤 1,直到宏任务执行完毕。这 4 步构成了一个事件的循环检测机制,即我们所称的eventloop。

4、本地存储及使用场景

共同点:都是保存在浏览器端,且都遵循同源策略。 不同点:在于生命周期与作用域的不同
作用域:localStorage只要在相同的协议、相同的主机名、相同的端口下,
就能读取/修改到同一份localStorage数据。sessionStorage比localStorage更严苛一点, 除了协议、主机名、端口外,还要求在同一窗口(也就是浏览器的标签页)下
cookie是网站为了标示用户身份而储存在用户本地终端上的数据(通常经过加密), cookie数据始终在同源的http请求中携带,记会在浏览器和服务器间来回传递。sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。

大小:cookie数据大小不能超过4k,sessionStorage和localStorage 虽然也有存储大小的限制,
但比cookie大得多,可以达到5M或更大。

时效:localStorage 存储持久数据,浏览器关闭后数据不丢失除非用户主动删除数据或清除浏览器/应用缓存;
sessionStorage 数据在当前浏览器窗口关闭后自动删除。

  1. 如何让cookie浏览器关闭就失效?——不对cookie设置任何正、负或0时间的即可;
  2. sessionStorage在浏览器多窗口之间 (同域)数据是否互通共享? ——不会,都是独立的, localStorage会共享;
  3. 能让localStorage也跟cookie一样设置过期时间?答案是可以的,在存储数据时,也存储 一个时间戳,

get数据之前,先拿当前时间跟你之前存储的时间戳做比较

5、重绘和回流

重绘和回流是渲染步骤中的一小节,但是这两个步骤对于性能影响很大。

  • 重绘是当节点需要更改外观而不会影响布局的,比如改变 color 就叫称为重绘
  • 回流是布局或者几何属性需要改变就称为回流。

回流必定会发生重绘,重绘不一定会引发回流。回流所需的成本比重绘高的多,改变深层次的节点很可能导致父节点的一系列回流。

减少重绘和回流

  1. 使用 translate 替代 top
  2. 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局)
  3. 把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow),然后你修改 100 次,然后再把它显示出来
  4. 不要把 DOM 结点的属性值放在一个循环里当成循环里的变量
  5. 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
  6. 动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用 requestAnimationFrame
  7. CSS 选择符从右往左匹配查找,避免 DOM 深度过深
  8. 将频繁运行的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于 video 标签,浏览器会自动将该节点变为图层。

6、浏览器缓存策略(强缓存,协商缓存)

强缓存
实现强缓存可以通过两种响应头实现:Expires 和 Cache-Control 。强缓存表示在缓存期间不需要请求,

Expires 是 HTTP / 1.0 的产物,表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。并且 Expires 受限于本地时间,如果修改了本地时间,可能会造成缓存失效。

Cache-Control 出现于 HTTP / 1.1,优先级高于 Expires 。该属性表示资源会在 30 秒后过期,需要再次请求

协商缓存
如果缓存过期了,我们就可以使用协商缓存来解决问题。协商缓存需要请求,如果缓存有效会返回 304。
协商缓存需要客户端和服务端共同实现,和强缓存一样,也有两种实现方式。
Last-Modified 和 If-Modified-Since
Last-Modified 表示本地文件最后修改日期,If-Modified-Since 会将 Last-Modified 的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。
但是如果在本地打开缓存文件,就会造成 Last-Modified 被修改,所以在 HTTP / 1.1 出现了 ETag 。
ETag 和 If-None-Match
ETag 类似于文件指纹,If-None-Match 会将当前 ETag 发送给服务器,询问该资源 ETag 是否变动,有变动的话就将新的资源发送回来。并且 ETag 优先级比 Last-Modified 高。

选择合适的缓存策略
对于大部分的场景都可以使用强缓存配合协商缓存解决,但是在一些特殊的地方可能需要选择特殊的缓存策略

  • 对于某些不需要缓存的资源,可以使用 Cache-control: no-store ,表示该资源不需要缓存
  • 对于频繁变动的资源,可以使用 Cache-Control: no-cache 并配合 ETag 使用,表示该资源已被缓存,但是每次都会发送请求询问资源是否更新。
  • 对于代码文件来说,通常使用 Cache-Control: max-age=31536000 并配合策略缓存使用,然后对文件进行指纹处理,一旦文件名变动就会立刻下载新的文件。

 

posted @ 2022-03-17 23:20  木子末  阅读(78)  评论(0)    收藏  举报