赞
踩
面试题及答案解析,大部分来自网络整理,我自己做了一些简化,内容有很多部分已经重复,解释也有些乱,大家带着自己的思考去看,整理自己的语言,如果想了解的更多,可以搜索一下,前端面试题宝典微信公众号或者查百度,另外如果出现错误请积极指正❤❤❤
以前我们总说,JS是单线程没有多线程,当JS在页面中运行长耗时同步任务的时候就会导致页面假死影响用户体验,从而需要设置把任务放在任务队列中
执行任务队列中的任务也并非多线程进行的,然而现在HTML5提供了我们前端开发这样的能力 - Web Workers API
概述:
web worker 是运行在后台的 js,独立于其他脚本,不会影响页面的性能
并且通过 postMessage 将结果回传到主线程
这样在进行复杂操作的时候,就不会阻塞主线程了
给JS多线程的环境
缺点:
worker一旦被建立,就会一直运行,不会被主线程的活动打断,但是会造成资源的浪费
限制:
document
、window
等对象,但是可以获取navigator
、location(只读)
、postMessage
方法来通信。alert
、confirm
,但可以使用 XMLHttpRequest
对象发出ajax请求注意:
实战场景:
用于浏览器根据宽,高和像素密度(分辨率)来加载相应的图片资源
注意:像素密度描述只对固定宽度图片有效
仅限于图片
<-- 属性格式: 图片地址 高度描述 像素密度描述(分辨率) -->
<img src="small.jpg" srcset="big.jpg 1440w, middle.jpg 800w, small.jpg 1x">
高度为 1440w 时加载big.jpg
高度为 800w 时加载middle.jpg
同的屏幕密度都要设置图片地址,目前的屏幕密度有1x,2x,3x,4x四种,如果每一个图片都设置4张图片,加载就会很慢
<img src="image-128.png"
srcset="image-128.png 128w, image-256.png 256w, image-512.png 512w"
sizes="(max-width: 360px) 340px, 128px" />
srcset指定图片的地址和对应的图片质量
sizes用来设置图片的尺寸零界点
label标签来定义表单控制间的关系
当用户选择该标签时,浏览器自动将焦点转到和标签相关的表单控件上
<label for="Name">Number:</label>
<input type='text' name="Name" id="Name"/>
<label>Date:<input type="text" name="B"/></label>
CSS不会阻塞DOM的解析,但是会影响JavaScript的运行
JavaScript会阻止DOM树的解析,最终CSS(CSSOM)会影响DOM树的渲染
类型分三种
JavaScript脚本在html页面中
<html>
<body>
<div>1</div>
<script>
let div1 = document.getElementsByTagName('div')[0]
div1.innerText = 'time.geekbang'
</script>
<div>test</div>
</body>
</html>
当解析到script标签时,HTML解析器暂停工作
JavaScript引擎介入,并执行scirpt标签中的这段脚本
脚本执行完成之后,HTML解析器回复解析过程
解析解析后续的内容,直至生成最终的DOM
html页面中引入javaScript文件
//foo.js
let div1 = document.getElementsByTagName('div')[0]
div1.innerText = 'time.geekbang'
<html>
<body>
<div>1</div>
<script type="text/javascript" src='foo.js'></script>
<div>test</div>
</body>
</html>
执行到JavaScript标签时,暂停整个DOM的解析
下载JavaScript文件,下载过程会阻塞DOM解析(下载速度受网络环境,文件大小等因素影响)
优化机制:
HLMT页面中有css样式
//theme.css
div {color:blue}
<html>
<head>
<style src='theme.css'></style>
</head>
<body>
<div>1</div>
<script>
let div1 = document.getElementsByTagName('div')[0]
div1.innerText = 'time.geekbang' // 需要 DOM
div1.style.color = 'red' // 需要 CSSOM
</script>
<div>test</div>
</body>
</html>
先等外部的CSS文件下载完成,并解析生成CSSOM对象
再执行JavaScirpt脚本
JavaScirpt引擎解析前是不知道是否存在了CSSOM,所以不管是否操作了都会执行CSS文件下载
再执行脚本
所以说,JavaScript脚本是依赖样式表的
DOM树
DOM是什么?DOM是文档对象模型,是一个树形结构,根节点是Document,用于存储文档中的节点对象。
可以通过DOM访问HTML元素的内容与联系,也可对其进行修改
CSS树
CSS树,又称CSSOM(CSS Object Model)是一个树形的文档结构,以树存储了各个选择器的映射以及相关样式属性,根节点是html
渲染树
构造DOM树,CSSOM树的时候也在同步构造渲染树(Render Tree),渲染树由DOM和CSSOM结合而成,通过DOM中的可视节点构造,并同时包含CSSOM对应的样式信息。渲染树构造完毕后将在屏幕上进行布局和绘制。
浏览器会下载HTML解析页面生成DOM树
遇到CSS标签就开始解析CSS
这个过程不会阻塞
但是如果遇到JS脚本,此时假如CSSOM还没有构建完
需要等待CSSOM构建完
再去执行JS脚本,然后再执行DOM解析
此时会阻塞
Broadcast Channel
顾名思义,“广播频道”,官方文档里的解释为“用于同源不同页面之间完成通信的功能”,在其中某个页面发送的消息会被其他页面监听到。
注意“同源”二字,该方法无法完成跨域的数据传输。
localStorage
localStorage是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(ps:session是会话级的存储空间,每个标签页都是单独的)。
SharedWorker
SharedWorker可以被多个window共同使用,但必须保证这些标签页都是同源的(相同的协议,主机和端口号)
WebSocket通讯
全双工(full-duplex)通信自然可以实现多个标签之间的通信
定时器setInterval+cookie
这样做确实可以实现我想要的功能,但是这样的方法相当浪费资源。虽然在这个性能过盛的时代,浪费不浪费也感觉不出来,但是这种实现方案,确实不够优雅。
postMessage
两个需要交互的tab页面具有依赖关系。
如 A页面中通过JavaScript的window.open打开B页面,或者B页面通过iframe嵌入至A页面,此种情形最简单,可以通过HTML5的 window.postMessage API完成通信,由于postMessage函数是绑定在 window 全局对象下,因此通信的页面中必须有一个页面(如A页面)可以获取另一个页面(如B页面)的window对象,这样才可以完成单向通信;B页面无需获取A页面的window对象,如果需要B页面对A页面的通信,只需要在B页面侦听message事件,获取事件中传递的source对象,该对象即为A页面window对象的引用:
//B页面
window.addEventListner('message',(e)=>{
let {data,source,origin} = e;
source.postMessage('message echo','/');
});
postMessage的第一个参数为消息实体,它是一个结构化对象,即可以通过“JSON.stringify和JSON.parse”函数还原的对象;第二个参数为消息发送范围选择器,设置为“/”意味着只发送消息给同源的页面,设置为“*”则发送全部页面。
HTML页面的生命周期包含三个重要事件:
每个事件都是有用的:
DomContentLoaded和脚本
当浏览器处理一个HTML文档,并在文档中遇到
因此,DOMContentLoaded肯定在下面的这些脚本执行结束之后发生
此规则有两个例外:
DomContentLoaded和样式
外部样式表不会影响DOM,因此DOMContentLoaded不会等待它们
但这里有一个陷阱:
如果在样式后面有一个脚本,那么该脚本必须等待样式表加载完成
脚本可不知道要不要用到样式相关属性,所以无论用到用不到,它都会等待样式加载完成
前面有一句说的好,脚本是依赖样式表的
浏览器内建的自动填充
Firefox,Chrome和Opera都会在DMOContentLoaded中自动填充表单
例如:
如果一个页面有一个带有登录名和密码的表单,并且浏览器记住了这些值
那么在DOMContentLoaded上,浏览器会尝试自动填充它们(如果用户允许)
因此,如果DOMContentLoaded被需要加载很长时间的脚本延迟触发
那么自动填充也会等待
如果你使用浏览器自动填充
登录和密码字段不会立即自动填充,而是在页面被完全加载钱会延迟填充
这实际上是DOMContentLoaded事件之前的延迟
window.onload
当整个页面,包括样式,图片和其他资源被加载完成时
会触发window对象上的load事件
可以通过onload属性获取此事件
window.onunload
当访问者离开页面时,window对象上的unload事件就会被触发
可以做一些不涉及延迟的操作
如果想通过unload事件,将页面使用数据,保存到服务器上
可以使用特殊的 navigator.sendBeacon(url, data) 方法
不会有延迟,即使浏览器离开页面,也会继续执行
当然,保存完数据后,往往已经离开页面了,所以也无法获取服务器返回的响应
window.onbeforeunload
如果想要离开页面或关闭窗口
beforeunload会进行多次确认
取消确认,浏览器会询问用户是否确定
capture 属性用于指定文件上传控件中媒体拍摄的方式。
可选值:
<input type='file' accept='image/*;' capture='camera'>
<input type="file" name="files" multiple/>
在输入input时会提示原来输入过的内容,还会出现下拉的历史记录,禁止这种情况只需在input中加入: autocomplete=“off”
<input type="text" autocomplete="off" />
autocomplete 属性是用来规定输入字段是否启用自动完成的功能。
不能,自闭合标签来自于XML语法,而不是HTML语法
iconfont是一种字体,但是不包含字母或数字,而是包含符号和字形
优点
不足
PV(页面访问量)
即页面浏览量或点击量
UV(独立访客)
访问你网站的一台电脑客户端为一个访客
DOM
Document,简称文档对象模型
通过创建树来表示文档,描述了处理网页内容的方法和接口
用DOM API 可以轻松地删除,添加和替换节点
BOM
browser object model ,简称浏览器对象模型
描述了与浏览器进行交互的方法和接口
(弹出浏览器窗口,移动,关闭窗口等)
BOM的核心是window,而window对象又具有双重角色
它既是通过js访问浏览器窗口的一个接口,又是一个Global(全局)对象
(是不是js初始化代码都是在 window load 属性中执行的)
这意味着在网页中定义的任何对象,变量和函数,都以window作为器global对象
DOM和BOM的联系和区别
联系
从window.document可以看出
DOM的最根本的对象是BOM的window对象的子对象document
(BOM的window对象的子对象是DOM)
区别
DOM描述了处理网页内容的方法和接口
BOM描述了与浏览器进行交互的方法和接口
像素
当设备尺寸相同,但像素变得更密集时,屏幕能显示的画面过渡更细致,图像看起来就更清晰明快
像素的分类
又称设备像素,指设备屏幕的物理像素,一个屏幕里的物理像素是固定的
又称CSS像素,是为web开发而创造的抽象概念,用于CSS和JavaScript中以【px】描述位置,大小和间距的单位尺寸
DPR
设备像素比
指默认屏幕内容无缩放时,物理像素和逻辑像素的比值
DPR = 物理像素/逻辑像素
再JavaScirpt里可以同过window.deviceRixelRatios获取用户设备的DPR值
概括:
Web页面中不是所有的图片都会加载和渲染!
归纳:
什么是viewport
viewport是用户网页的可视区域
手机浏览器是把页面放在一个虚拟的“窗口”(viewport)中
通常这个虚拟的“窗口”比屏幕宽
这样就不用把每个网页挤到很小的窗口中
用户可以通过平移和缩放来看网页的不同部分
设置Viewport
一个常用的针对移动网页优化过的页面
<meta name="viewport" content="width=device-width, initial-scale=1.0">
页面加载自上而下
当然是先加载样式
渲染机制的区别:
在body前是已经把样式浏览一遍,到了对应标签直接,渲染样式,显示快
在body后,是浏览器已经把标签浏览了,但基于没有样式,显示的不完全,再把body后的样式表,扫描后,在成为真正的样式,会慢,可能会出现FOUC现象(即样式失效导致的页面闪烁问题)
遇到大型网站,效果更差,这都基于浏览器从上而下的浏览机制导致的
link属于HTML标签,而@import是css提供的
页面被加载时,link会同时被加载,而@import引用的css会等到页面被加载完再加载
@import只在IE5以上才能识别,而link是XHTML标签,无兼容问题
link方式的样式的权重高于@import的权重
下面我们来看看具体的细节。
DNS解析
DNS解析实际上就是寻找你所需要的资源的过程。假设你输入www.baidu.com,而这个网址并不是百度的真实地址,互联网中每一台机器都有唯一标识的IP地址,这个才是关键,但是它不好记,乱七八糟一串数字谁记得住啊,所以就需要一个网址和IP地址的转换,也就是DNS解析。
DNS解析其实是一个递归的过程。
输入www.google.com网址后,首先在本地的域名服务器中查找,没找到去根域名服务器查找,没有再去com顶级域名服务器查找,,如此的类推下去,直到找到IP地址,然后把它记录在本地,供下次使用。大致过程就是.-> .com ->google.com. -> www.google.com.。 (最后这个.对应的就是根域名服务器,默认情况下所有的网址的最后一位都是.,为了方便用户,通常都会省略,浏览器在请求DNS的时候会自动加上)
DNS优化
既然已经懂得了解析的具体过程,我们可以看到上述一共经过了N个过程,每个过程有一定的消耗和时间的等待,因此我们得想办法解决一下这个问题!
DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种: 浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。
比如访问baidu.com的时候,每次响应的并非是同一个服务器(IP地址不同),一般大公司都有成百上千台服务器来支撑访问。DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡。
发起TCP连接
TCP提供一种可靠的传输,这个过程涉及到三次握手,四次挥手。
三次握手
客户端发送syn包(Seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(Seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
四次挥手
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,假设客户端主动关闭,服务器被动关闭。
客户端发送一个FIN,用来关闭客户端到服务器的数据传送,也就是客户端告诉服务器:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,客户端依然会重发这些数据),但是,此时客户端还可以接受数据。
FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
服务器收到FIN包后,发送一个ACK给对方并且带上自己的序列号seq,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
服务器发送一个FIN,用来关闭服务器到客户端的数据传送,也就是告诉客户端,我的数据也发送完了,不会再给你发数据了。由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
至此,完成四次挥手。
发送HTTP请求
发送HTTP请求,就是构建HTTP请求报文,并通过TCP协议,发送到服务器指定端口。
请求报文由请求行
,请求报头
,请求正文
组成。
服务器处理请求并返回HTTP报文
对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般是由Web服务器去进行,比如Tomcat, Nginx和Apache等Web服务器。
HTTP报文也分成三段:状态码
,响应报头
和响应报文
。
浏览器解析渲染页面
这个图就是Webkit解析渲染页面的过程。
后续会继续更新!冲冲✨✨✨
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。