浏览器面试题(面试系列)
cookie 与 本地存储 相关
cookie、session、localStorage 分别是什么?
cookie 是存储在浏览器上的一小段数据,用来记录某些当页面关闭或者刷新后仍然需要记录的信息。
用户在输入用户名密码提交给服务端,服务端验证通过后会创建一个 session 用于记录用户的相关信息,这个 session 可保存在服务器内存中,也可保存在数据库中。
localStorage HTML5 本地存储 web storage 特性的 API 之一,用于将大量数据(最大 5M)保存在浏览器中,保存后数据永远存在不会失效过期,除非用 JS 手动清除。
cookie 的使用
1 | // 设置 |
cookie, localStorage 和 sessionStorage 的区别
用途
- cookie:是服务器发给浏览器保存的(字符串)数据,一般用来记录用户信息方便服务端确认用户身份
- localStorage、sessionStorage:本地存储,可以保存一些不太重要的数据,例如当前用户坐标,购物车信息等
存储大小
- cookie:4k
- localStorage, sessionStorage:5M
有效期
- cookie:关闭浏览器失效(默认)
- localStorage:永久,除非 js 手动删和清除浏览器缓存
- sessionStorage:页面不关闭就不失效,包括重新加载或恢复页面也不失效。但在新标签或窗口打开一个页面,则会重新生成
cookie 与 session 区别
都是用来确认用户身份的,区别在于 cookie 保存在客户端,session 保存在服务端。
另外,session 是基于 cookie 的。服务器端在生成 session 后,会让客户端的 cookie 代为保存 sessionID 。
阅读:
- 一文带你看懂 cookie,面试前端不用愁
- 聊一聊 cookie
- Cookie 禁用了,Session 还能用吗?
- session,cookie,sessionStorage,localStorage 的区别及应用场景
如何实现同一个浏览器多个标签页之间的通信?
1. websocket 通讯
全双工(full-duplex)通信自然可以实现多个标签页之间的通信。
2. 定时器 setInterval+cookie
在页面 A 设置一个使用 setInterval 定时器不断刷新,检查 Cookies 的值是否发生变化,如果变化就进行刷新的操作。
3. 使用 localStorage
localStorage 是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(ps:session 是会话级的存储空间,每个标签页都是单独的)。
直接在 window 对象上添加监听即可:
1 | window.onstorage = e => { |
HTML5 的离线储存使用,解释工作原理?
在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。 原理:HTML5 的离线存储是基于一个新建的 .appcache 文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像 cookie 一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示。
如何使用:
- 页面头部像下面一样加入一个 manifest 的属性
- 在 cache.manifest 文件的编写离线存储的资源
- 在离线状态时,操作 window.applicationCache 进行需求实现。
详细的使用请参考:
浏览器对 HTML5 离线储存资源的管理和加载?
在线的情况下:
浏览器发现 html 头部有 manifest 属性,它会请求 manifest 文件,如果是第一次访问 app ,那么浏览器就会根据 manifest 文件的内容下载相应的资源并且进行离线存储。如果已经访问过 app 并且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的 manifest 文件与旧的 manifest 文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,那么就会重新下载文件中的资源并进行离线存储。
离线的情况下:
浏览器就直接使用离线存储的资源。
用户点外卖的份数怎么和后台通信?万一用户中断了再进了怎么获取?为什么不用 cookie?
- 将购物车信息存在 localStorage
- 从 localStorage 中获取
- 用户禁用 cookie 时无法使用
兼容性
经常遇到的浏览器的兼容性有哪些?
- IE 浏览器不支持 Promise
- babel-polyfill → webpack.config.js 的 entry 中设置 [‘babel-polyfill’, ‘./src/main.js’]
- 各浏览器之间默认样式的差异
- normalize.css
- 与 reset 区别 → normalize.css 消除各浏览器之间默认样式的差异、保留有用的默认样式;而 reset 会清除所有的默认样式,过于暴力,例如会让 h 标题标签不再默认加粗,ul li 前面默认的小圆点也没了)
- normalize.css
- html5 某些新增标签不被识别
- html5shiv.js - 解决 ie9 以下对 html5 某些新增标签不识别的问题(e.g. video 标签不识别不显示)
- 用法:
[if lt IE 9]><script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script><![endif]
- 用法:
- 通过 document.createElement 方法产生的标签, 可以利用这一特性让这些浏览器支持 HTML5 新标签,浏览器支持新标签后,还需要添加标签默认的样式。
- html5shiv.js - 解决 ie9 以下对 html5 某些新增标签不识别的问题(e.g. video 标签不识别不显示)
- CSS3 媒体查询失效
- respond.js - 能解决 ie9 以下不支持媒体查询问题
- 自动添加浏览器前缀
- posscss-loader+autoprefixer
- ie6 不支持 min-height/width
- 添加额外的
_min-height
ie6 识别
- 添加额外的
- 常见 hack(针对特定 ie 版本的样式控制)
- _color - ie6 识别
- *color - ie6/7 识别
- color: red\9; ie8 及以下识别
- ie 条件注释写法:(lt 小于 | gt 大于 | lte 小于等于 | gte 大于等于 | ! 不等于)
移动端兼容性呢?
- 移动端点透问题
- ios 滚动卡顿
- 使用 better-scroll 插件
- ios 顶部输入框 fixed 布局失效(当键盘弹起时)❌
- 安卓 键盘遮挡输入框 ❌
position:fixed; 在 android 下无效怎么处理?【❌ 待验证】
原因:
fixed 的元素是相对整个页面固定位置的,你在屏幕上滑动只是在移动这个所谓的 viewport ,
原来的网页还好好的在那,fixed 的内容也没有变过位置。
解决:
1 | <meta |
移动端的点击事件的有延迟,时间是多久,为什么会有? 怎么解决这个延时?❌
click 有 300ms 延迟,为了实现 safari 的双击事件的设计,浏览器要知道你是不是要双击操作。
在做移动端项目时遇到过什么问题?
参考阅读:H5 与 APP 混合开发遇到的问题总结
Polyfill
什么是 Polyfill
polyfill 是“在旧版浏览器上复制标准 API 的 JavaScript 补充”,可以动态地加载 JavaScript 代码或库,在不支持这些标准 API 的浏览器中模拟它们。
例如,geolocation(地理位置)polyfill 可以在 navigator 对象上添加全局的 geolocation 对象,还能添加 getCurrentPosition 函数以及“坐标”回调对象,
所有这些都是 W3C 地理位置 API 定义的对象和函数。
因为 polyfill 模拟标准 API,所以能够以一种面向所有浏览器未来的方式针对这些 API 进行开发,
一旦对这些 API 的支持变成绝对大多数,则可以方便地去掉 polyfill,无需做任何额外工作。
做的项目中,有没有用过或自己实现一些 polyfill 方案(兼容性处理方案)?❌
比如: html5shiv、Geolocation、Placeholder
列举 IE 与其他浏览器不一样的特性?
事件目标对象
触发事件的元素被认为是目标(target)。而在 IE 中,目标包含在 event 对象的 srcElement 属性
获取字符代码
如果按键代表一个字符(shift、ctrl、alt 除外),IE 的 keyCode 会返回字符代码(Unicode),DOM 中按键的代码和字符是分离的,要获取字符代码,需要使用 charCode 属性
阻止某个事件的默认行为
IE 中阻止某个事件的默认行为,必须将 returnValue 属性设置为 false,Mozilla 中,需要调用 preventDefault() 方法
停止事件冒泡
IE 中阻止事件进一步冒泡,需要设置 cancelBubble 为 true,Mozzilla 中,需要调用 stopPropagation()
通信
如何实现浏览器内多个标签页之间的通信? (阿里)
WebSocket、SharedWorker;
也可以调用 localStorage 、cookies 等本地存储方式;
localStorage 另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件, 我们通过监听事件,控制它的值来进行页面信息通信;
注意:Safari 在无痕模式下设置 localStorage 值时会抛出 QuotaExceededError 的异常;
webSocket 如何兼容低浏览器?(阿里)
Adobe Flash Socket 、 ActiveX HTMLFile (IE) 、 基于 multipart 编码发送 XHR 、 基于长轮询的 XHR
页面渲染与缓存
从输入 URL 到页面展现中间发生了什么?
DNS 查询
建立 TCP 连接(三次握手)
发送 HTTP 请求
服务端 web 服务器对请求做处理(监听 80 端口 路由 渲染 HTML 模板 生成响应)
发送 HTTP 响应
关闭 TCP 连接(四次挥手)
浏览器解析 HTML,CSS,图片,JS
处理 HTML 标记并构建 DOM 树
处理 CSS 标记并构建 CSS 规则树
将 DOM 树 与 CSS 规则树 合并成一个渲染树。
根据渲染树来布局,以计算每个节点的几何信息。
将各个节点绘制到屏幕上
这五个步骤并不一定一次性顺序完成。如果 DOM 或 CSSOM 被修改,以上过程需要重复执行,这样才能计算出哪些像素需要在屏幕上进行重新渲染。实际页面中,CSS 与 JavaScript 往往会多次修改 DOM 和 CSSOM
阅读更多:
style 标签写在 body 后与 body 前(head)有什么区别?
style 标签放在 body 后,会导致当加载到此样式时,页面将停止之前的渲染。此样式表被解析后,将重新渲染页面,也就出现了短暂的花屏现象。
所以不要写在 body 后,要把样式放在 head 中。
缓存策略执行过程
一个 Response Header 示例
强缓存与协商缓存的异同
- 相同点:最终都是走的本地缓存
- 不同点:强缓存不发请求,直接读本地缓存。协商缓存发请求到服务器
基本原理
- 1)浏览器在加载资源时,根据请求头的
expires
和cache-control
判断是否命中强缓存,是则直接从缓存读取资源,不会发请求到服务器。 - 2)如果没有命中强缓存,浏览器一定会发送一个请求到服务器,通过
last-modified
和Etag
验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源 - 3)如果前面两者都没有命中,直接从服务器加载资源
如何实现页面每次打开时清除本页缓存?
- 用 HTML 标签设置 HTTP 头信息:
1 | <meta http-equiv="Pragma" content="no-cache" /> |
说明:HTTP 头信息 Expires 和 Cache-Control 为应用程序服务器提供了一个控制浏览器和代理服务器上缓存的机制。
HTTP 头信息 Expires 告诉代理服务器它的缓存页面何时将过期。
HTTP1.1 规范中新定义的头信息 Cache-Control 可以通知浏览器不缓存任何页面。当点击后退按钮时,浏览器重新访问服务器已获取页面。
如下是使用 Cache-Control 的基本方法:
1)no-cache:强制缓存从服务器上获取新的页面;
2)no-store:在任何环境下缓存不保存任何页面。
HTTP1.0 规范中的 Pragma: no-cache 等同于 HTTP1.1 规范中的 Cache-Control: no-cache,同样可以包含在头信息中。
- 在需要打开的 url 后面增加一个随机的参数:
增加参数前:url=test/test.jsp
增加参数后:url=test/test.jsp?ranparam=random()
expires 和 cache-control 的区别
都是用的本地系统时间,但
- expires 存的是个服务端绝对时间,修改客户端系统时间会有影响
- cache-control 是相对时间,即使客户端时间发生改变,相对时间也不会随之改变。例如设置 max-age = 10s,那么在 10s 以内,使用浏览器缓存的资源
- cache-control 的优先级高于 expires
http get 和 post 区别
- 语义:GET 用来读数据,POST 用来写数据
- 参数:GET 放在 url 里,POST 放消息体里
- 大小:GET 长度有限制,一般 1024 个字符。POST 4~10Mb 限制
- 缓存:GET 请求可以被浏览器缓存,POST 不能
cache-control 和 Etag 的区别
一个不发请求,一个发请求。超过缓存时间,只要 if-None-Match 和服务器端 etag 相同,仍然缓存。并且 Etag 比 cache-control 的优先级更高。
http 和 https 的区别
HTTPS
是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。
HTTPS 作用
- 一种是建立一个信息安全通道,来保证数据传输的安全
- 另一种就是确认网站的真实性。
区别
- https 协议需要到 ca 申请证书,有免费付费可选
- http 是明文传输,https 则是具有安全性的 ssl 加密传输协议。
- 非对称加密
- 性能问题:https 做了加密就意味着客户端服务端也需要附带解密步骤,相比来说,在通讯快捷上,性能有所不如 http 。
对非对称性加密的理解
不要去硬记。 你只要想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
参考:
介绍 HTTPS 握手过程
- 客户端使用 https 的 url 访问 web 服务器,要求与服务器建立 ssl 连接
- web 服务器收到客户端请求后, 会将网站的证书(包含公钥)传送一份给客户端
- 客户端收到网站证书后会检查证书的颁发机构以及过期时间, 如果没有问题就随机产生一个秘钥
- 客户端利用公钥将会话秘钥加密, 并传送给服务端, 服务端利用自己的私钥解密出会话秘钥
- 之后服务器与客户端使用秘钥加密传输
参考来源:
阅读更多:
HTTP1.1 与 HTTP2 的区别
- 基于 HTTPS 的
- 多路复用
- 服务端推送
简单讲解一下 http2 的多路复用
阅读更多:多路复用
HTTP2 采用二进制格式传输,取代了 HTTP1.x 的文本格式,二进制格式解析更高效。
多路复用代替了 HTTP1.x 的序列和阻塞机制,所有的相同域名请求都通过同一个 TCP 连接并发完成。在 HTTP1.x 中,并发多个请求需要多个 TCP 连接,浏览器为了控制资源会有 6-8 个 TCP 连接都限制。
HTTP2 中:
- 同域名下所有通信都在单个连接上完成,消除了因多个 TCP 连接而带来的延时和内存消耗。
- 单个连接上可以并行交错的请求和响应,之间互不干扰。
阅读更多:
性能优化
你有用过哪些前端性能优化的方法?
资源合并压缩
- 压缩
- html,css,js【html-webpack/optimize-css-assets/webpack-parallel-uglify】-plugin
- 图片:image-webpack-loader,雪碧图,iconfont 图标字体
- 合并
- 减少 http 请求,每个 http 请求都带来慢启动,三次握手,连接建立,所以资源合并由为重要
- 服务端启用 gzip(压缩率 80%)
- 浏览器请求 header 设置 accept-encoding: gzip
- 服务器响应 header 返回 content-encoding: gzip【apache 的 httpd.conf】
浏览器加载原理优化
原理:html 在转 DOM 时,节点引用 css/img 不影响继续转化,但 js 会阻塞,因为 js 有可能修改 dom 树
- css 放 head
- js 尽量不放 head,如果放则 js 内嵌,且在所有 css 前面 | 对于会阻塞后续内容的外部 js ,用 defer
- 首屏优化
- 懒加载:列表滚动图片懒加载
- 按需加载 webpack codespliting
- 使用 cdn 加速:把静态资源(能被浏览器缓存的 js/css)分发到离用户最近节点就近获取,提高响应速度和成功率
缓存优化
- http 协议缓存:强缓存/协商缓存
- 使用浏览器缓存来减少请求数量
- css,js 加 MD5 后缀
- 本地存储 localStorage (地理位置,购物车)
- app cache ❌
- service worker ❌
渲染优化
- 减少重绘和重排
- 集中改变样式(cssText,类名切换)
- 批量修改 DOM(display:none,createDocumentFragment)
- 读写分离(尽量不要一行代码又读又写 div.style.left = div.offsetLeft + 1 + ‘px’; <=重复两次就是两次重排,先存起来就只会导致一次重排)
- 动画
- css3 动画
- webkit-transform: translateZ(0); / will-change: transform;
- GPU 渲染,浏览器生成 DOM 元素快照,在 GPU 的层上缓存起来做单独做动画
- webkit-transform: translateZ(0); / will-change: transform;
- js 动画
- 使用 requestAnimationFrame 提升流畅度(确保 js 尽早在每一帧开始时执行)
- css3 动画
- 列表滚动重用(类似 ios cell 复用)❌
- 使用 SSR(server side rendering)后端渲染,数据直接输出到 HTML ❌
其它
检测浏览器版本版本有哪些方式?
功能检测、userAgent 特征检测
1 | 比如:navigator.userAgent |
判断用户的浏览器类型
1 | function isAndroid() { |
介绍一下你对浏览器内核的理解
主要分成两部分:
渲染引擎(Layout engineer 或 Rendering Engine)和 JS 引擎。
- 渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。
- JS 引擎则:解析和执行 javascript 来实现网页的动态效果。 最开始渲染引擎和 JS 引擎并没有区分的很明确,后来 JS 引擎越来越独立,内核就倾向于只指渲染引擎。
详细文章:浏览器内核的解析和对比
常见状态码
形象记忆:https://http.cat/
- 200 服务器成功返回请求
- 301 永久重定向,浏览器会记住 | 302 临时重定向 | 304 请求页面未修改
- 400 请求错误,服务器不理解 | 401 请求未授权 | 403 服务器拒绝请求 | 404 资源不存在 | 405 方法禁用
- 500 服务器内部错误 | 503 服务暂时不可用(超载 or 停机维护)
谈谈你对 TCP 三次握手和四次挥手的理解
页面可见性(Page Visibility API)有哪些用途
- 通过 visibilityState 的值检测页面当前是否可见,以及打开网页的时间等;
- 在页面被切换到其他后台进程的时候,自动暂停音乐或视频的播放;
网页验证码干嘛的,是为了解决什么安全问题
区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水;
有效防止黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
如果需要手动写动画,你认为最小时间间隔是多久,为什么?
多数显示器默认频率是 60Hz,即 1 秒刷新 60 次,所以理论上最小间隔为 1/60*1000ms = 16.7ms
第一次访问页面中时弹出引导,用户关闭引导,之后再次进入页面时不希望出现引导,如何实现?❌
localStorage
实现一个页面操作不会整页刷新的网站,并且能在浏览器的前进,后退时正确响应。给出你的技术实现方案?
- onhashchange
- window.history.pushState(添加新的历史记录)/replaceState(state,title, url)【改掉当前历史记录】
- 配合 onpopstate 事件来监听历史记录的改变
websocket
实现了客户端与服务端之间的全双工通信,当服务端数据变化时,可以第一时间通知到客户端。
与 HTTP 的区别
- http 只能由客户端发起,而 webSocket 是双向的
- webSocket 传输的数据包相对于 http 而言很小,很适合移动端使用
- 没有同源限制,可以跨域共享资源
TCP 和 UDP
TCP(Transmission Control Protocol,传输控制协议)
是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。 一个 TCP 连接必须要经过三次“对话”才能建立起来
TCP 三次握手过程
- 第一次握手:主机 A 通过向主机 B 发送一个含有同步序列号的标志位的数据段给主机 B ,向主机 B 请求建立连接,通过这个数据段, 主机 A 告诉主机 B 两件事:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我。
- 第二次握手:主机 B 收到主机 A 的请求后,用一个带有确认应答(ACK)和同步序列号(SYN)标志位的数据段响应主机 A,也告诉主机 A 两件事:我已经收到你的请求了,你可以传输数据了;你要用那个序列号作为起始数据段来回应我
- 第三次握手:主机 A 收到这个数据段后,再发送一个确认应答,确认已收到主机 B 的数据段:”我已收到回复,我现在要开始传输实际数据了,这样 3 次握手就完成了,主机 A 和主机 B 就可以传输数据了。
TCP 断开连接要进行 4 次
- 第一次: 当主机 A 完成数据传输后,将控制位 FIN 置 1,提出停止 TCP 连接的请求 ;
- 第二次: 主机 B 收到 FIN 后对其作出响应,确认这一方向上的 TCP 连接将关闭,将 ACK 置 1;
- 第三次: 由 B 端再提出反方向的关闭请求,将 FIN 置 1 ;
- 第四次: 主机 A 对主机 B 的请求进行确认,将 ACK 置 1 ,双方向的关闭结束。
UDP(User Data Protocol,用户数据报协议)
UDP 是一个非连接的协议,传输数据之前源端和终端不建立连接, 当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。
TCP 与 UDP 的区别
1、TCP 面向连接;UDP 不面向连接;
2、TCP 传输可靠(三次握手),UDP 则不可靠,不保证正确性(UDP 传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发);
3、UDP 开销小,传输快;
使用场景
- TCP:效率要求相对低,但对准确性要求相对高的场景(文件传输,邮件接收,远程登录)
- UDP:效率要求相对高,但对准确性要求相对低的场景(在线视频,语音电话)
网络七层协议
CDN 是什么
Content Delivery Network,简称 CDN,翻译成中文是内容分发网络。
CDN 是通过在网络上的各个地方放置一定数量的节点服务器,构成在现有的互联网基础之上的一层智能虚拟网络,这层网络的主要功能是将信息(源站内容)分发至靠近用户的各个节点服务器上,让用户可以就近获取所需信息。
通过 CDN,可以有效降低源站的访问压力,减轻骨干网络的拥塞,提升用户的访问速度,从而提升用户体验。还可在一定程度上保障源站的安全。
CDN 的用途可以说很窄,也可以说很广。说窄是因为 CDN 只是基于互联网之上的一种服务,只是给网络/网站加速的;说广是因为几乎所有的互联网业务(如网页、电商、APP、游戏、下载、影视点播、直播等等)都需要用到 CDN ,而如今互联网又无处不在。
来源:https://www.zhihu.com/question/282510029/answer/427307826