浏览器
一、浏览器输入一个url会发生什么事情?
1.输入一个url之后
2.首先会去读缓存,有缓存的情况下就去走缓存,没有的话就会往下执行
3.解析域名,dns,ip等,在解析端口
4.三次握手 建立TCP连接
5.http请求 或者https请求
6.四次挥手 关闭连接
7.解析html css js (其中html、js是从上往下、从左往右执行,css是从右往左,例如#a .b span{color:#fff} 会先解析color然后会找span 再找class为b的标签 在找id为a的标签,这也解释了,id选择器大于类选择器,类选择器大于元素选择器,这个级别关系)这就是浏览器渲染
二、浏览器是如何解析代码的?
1-1 渲染过程
1.浏览器的渲染引擎(GUI引擎)会通过html Parser解析html并且生成dom Tree。
2.浏览器的渲染引擎(GUI引擎)会通过css Parser解析css并且生成style Rules。
3.dom Tree和style Rules结合会生成一个新的对象,也就是我们常说的Render Tree,结合layout绘制在屏幕上,从而展现出来。
-
渲染引擎通常会把解析出来的内容尽快展示出来,并不会等到html都被解析完成并创建渲染树。它会在处理后续内容的同时把处理过的局部先展示出来。
-
浏览器的解析器把工作分为两个组件——分词程序负责把输入切分成合法符号序列,解析程序负责按照语法规则分析文档结构和构建句法树。词法分析器知道如何过滤像空格、换行之类的无关字符。
-
Webkit 使用了自动代码生成工具生成了相应的代码,也就是说
词法分析
和语法分析
这部分代码是自动生成的,而 Webkit 中实现的 CallBack 函数就是在 CSSParser 中
2-2解析css
#molly div .haha span {color:#f00}
1.CSS选择器的读取顺序是从右向左。
2.如上面代码块,会先找到span顺着往上找到class为haha的div,再找到id为molly的元素
3.成功匹配则加入结果集,如果直到根元素都没有匹配,则不再便利这条路径,从下一个span开始重复这个过程
4.整个过程会形成一条符合规则的索引树,树由上至下的节点是规则中从右往左的一个个选择符匹配的节点
5.如果从左向右的顺序读取,在执行到左边的分之后发现没有相对应元素匹配,则回溯到上一个节点再继续遍历,直到找到或者没有相匹配的元素才结束。(如果有成百上千个分支的时候会消耗很多性能,反之从右往左查找极大的缩小查找范围,从而提高了性能。)
这就解释了id选择器大于类选择器,类选择器大于标签选择器
3-3解析js
遵循从上到下、从左到右的执行规则,这也是作用域产生的原因
垃圾回收机制
标记清除
垃圾收集器会给所有的变量都加上标记,然后会去掉环境中的变量,以及被环境引用的变量。后面的这些被标记的变量就会被浏览器删除,释放占用空间(这就是当前的主流GC算法,v8里面就是用这种)
引用计次
引用计次的含义就是跟踪记录每个值被引用的次数,当声名了一个变量并且将一个引用类型赋值给该变量时,这个值的引用次数就是1。相反,如果包含这个值引用的变量又取得了另一个值,则这个值的引用次数减1。当引用次数变为0时,则说明没有办法访问这个值了,因而就可以收回这个值的内存空间。垃圾收集器下次运行时,就会释放引用次数为0的值所占用的内存。
本地储存
cookie
特点:存储量少4k左右,会与服务器通信,每次都会携带在http头中(cookie最开始被设计出来并不是做存储的,而是为了http请求在管理状态上的不足)
-
键值对,必须字符串类型,如果是unicode字符,需要为字符编码如果是二进制,则需要base64编码
-
domain,指定cookie所属域名,默认是当前域名
-
path,指定cookie在哪个路径(路由)下生效,默认‘ / ’。如果设置'/abc',那么只在abc页面能访问到cookie。
-
maxAge,失效时间
-
expires,失效时间
-
secure,是否仅被安全协议传输,安全协议有https、SSL等,默认是false
-
httponly,无法通过js获取到cookie,只能在application中去修改,一定程度上防止了XSS攻击,不是绝对的安全
localStorage
特点:存储量大(5M-10M,浏览器不同),除非主动删除,否则一直会在
sessionStorage
特点:存储量大(5M-10M,浏览器不同),关闭对话框的时候会删掉,称为会话级存储
webSQL
特点:存储功能强大,类型也更多(例如视频,图片等),可以操作本地数据库的网页API接口,用sql语句可以对数据进行增删改查。比如 Chrome 和 Safari 会用 SQLite 实现本地存储,微信就采用了 SQLite 作为本地聊天记录的存储。
indexedDb
特点:键值对存储,异步(操作不会锁死浏览器),支持事务,同源限制,空间大(250M),支持二进制存储
浏览器线程
GUI线程(html解析器会解析html生成dom tree,css解析器会解析css生成style rules,两者结合会生成render tree,结合layout,就会展示在页面)
js引擎线程(会和GUI渲染线程互斥,因为js可以操作dom)
事件触发线程
定时触发器线程
http异步线程
浏览器兼容
css hack
在CSS方面,我们可以使用CSS Hack。CSS hack是通过在CSS样式中加入一些特殊的符号也就是浏览器前缀,让不同的浏览器识别不同的符号(什么样的浏览器识别什么样的符号是有标准的,CSS hack就是让你记住这个标准),以达到应用不同的CSS样式的目的。
polyfill
在JS方面,我们可以使用polyfill。polyfill 是一段代码(或者插件),提供了那些开发者们希望浏览器原生提供支持的功能。程序库先检查浏览器是否支持某个API,如果不支持则加载对应的 polyfill。比如,html5的storage。不同浏览器,不同版本,有些支持,有些不支持。其实polyfill就是shim的一种。 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
postcss
PostCSS是一个利用JS插件来对CSS进行转换的工具,这些插件非常强大,强大到无所不能。其中,Autoprefixer就是众多PostCSS插件中最流行的一个。
modernizr
Modernizr.js十分的强大,既能给老版本浏览器打补丁,又能保证新浏览器渐进增强的用户体验。
Modernizr默认做的事情很少,除了(在你选择的情况下)给不支持html5的标签的浏览器,如IE6,7,8追加一点由Remy Sharp开发的html5垫片脚本,使其识别html5元素之外,它主要做的就是浏览器功能检测。因此,它知道浏览器是否支持各种html5和css3特性。
浏览器安全
1.跨站脚本(XSS)
2.跨站请求伪造(CSRF)
3.界面操作劫持
4.漏铜挖掘
5.WEB蠕虫
6.控制台注入代码
7.钓鱼
防御:
请求来源限制——验证 HTTP Referer 字段
额外验证机制——token的使用
浏览器缓存
缓存机制
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match) 协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。
强缓存
浏览器不走http请求,直接读取缓存
-
http1.0:Expires字段(既过期时间),存在于服务端返回的响应头中,告诉浏览器这个过期时间可以直接从浏览器的缓存里获取数据 例:
Expires: Wed, 22 Nov 2019 08:41:00 GMT
说明资源在2019-11-22 8:41分过期,但是犹豫服务器时间和浏览器时间可能是不相同的,所以这个时间也就是不准确的,后面在http1.1时期就抛弃了 -
http1.1:通过Cache-Control字段,可以设置多个属性例如(Expires和Cache-Control同时存在Cache-Control优先级高) max-age(采用过期时长来控制缓存例如
Cache-Control:max-age=3600
代表3600s之内可以读取缓存) private:只有浏览器缓存,不接受代理服务器缓存 no-cache:跳过当前强缓存,发出http请求,既直接进入协商缓存 no-store:非常暴力,不接受任何形式的缓存 s-maxage:针对代理服务器的缓存时间
协商缓存
强缓存失效后,通过http请求携带缓存标志发送给服务端,服务端根据Last-Modified和ETag这两个字段,来决定是否使用缓存
协商缓存生效,返回304和Not Modified
协商缓存失效,返回200和请求结果
首先在精确度上,Etag要优于Last-Modified。 Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。
第二在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。 第三在优先级上,服务器校验优先考虑Etag
缓存位置
Service worker
Memory Cache
Disk Cache
Push Cache
回流和重绘
回流:当我们对dom结构修改引发dom几何尺寸变化(增减或者移动)的时候会发生回流(width、height、padding、left、margin、border等)
重绘:当dom几何属性没有变化,只有样式的变化,会发生重绘
-
回流会导致重绘,重绘不一定导致回流
https
https并不是一个全新的协议,只是一个加强版的http。https在http数据和tcp层传输中建立了一个安全层,利用对称加密和非对称加密结合数字证书认证的方式,让传输过程的安全性大大提高。
数字证书:服务器运营者需要向第三方认证机构获取授权,这个第三方机构叫CA机构,认证通过后,CA认证机构会给服务器办法数字证书。
-
服务器向浏览器证明自己的身份
-
把公钥传给服务器
http的特性是明文传输,http数据在和tcp层、wifi路由器、运行商、目标服务器之前传输时,可能在任一环节被获取数据并且篡改(中间人攻击),为了防范这一类攻击,引入了新的加密方案——https
-
对称加密:是指加密与解密用的相同的秘钥
-
非对称加密:是指有两把秘钥,如果用A秘钥加密过的数据包只能用B秘钥解密,反之B秘钥加密过的数据只能用A解密。
对称加密加解密过程
-
浏览器会将client_random和加密方法列表发送给服务器
-
服务器接受后会给浏览器发送server_random和加密方法
-
浏览器和服务器之间都拥有了client_random、server_random以及加密方法
-
用这个加密发放将两个随机数以特定的方法结合起来就生成了秘钥,这个秘钥就是浏览器与服务器通讯的暗号
对应效果:如果用对称加密的方式,那么第三方可以在中间获得client_random、server_random以及加密方法,犹豫加密方法同时也是解密方法,所以对称加密这种方式很容易被破解
非对称加密加解密过程
-
浏览器会将client_random和加密方法列表发送给服务器
-
服务器接受后会给浏览器发送server_random、加密方法和公钥
-
浏览器和服务器都拥有了client_random、server_random以及加密方法
-
浏览器用公钥将client_random、server_random加密,生成与服务器的暗号
-
这是非对称加密,公钥加密过的数据只能用私钥解密,因此中间人就算拿到了浏览器传来的数据,也没有私钥无法解密,保证了数据的安全性
对应效果:这样也不一定安全,非对称加密的定义(公钥可以解密私钥加密过的数据包,那么私钥也可以解密公钥加密过的数据包),所以只要中间人一旦拿到公钥照样可以解密数据,这样也可以破解非对称加密
结论:https使用对称加密或者非对称加密任意一种,都会产生安全隐患,所以为了保证安全,实际是把他们俩结合起来,来保证安全!!!!
对称加密和非对称加密结合
-
浏览器会将client_random和加密列表发送给服务器
-
服务器接受后会给浏览器发送server_random、加密方法和公钥
-
浏览器接收,会再次生成一个pre_random,并且用公钥加密,传给服务器
-
服务器用私钥解密这个被加密后的pre_random
-
现在浏览器和服务器都有client_random、server_random、pre_random,然后两者用相同的加密方法混合这三个随机数,生成最终的秘钥。
防抖和节流
防抖:
每次事件触发则删除原来的定时器,建立新的定时器。(类似于王者的回城,反复触发回城技能,只会执行最后一次)
节流:
每次事件触发在定时器的范围内则不予理睬,等当前定时器完成,事件触发才能启动下一个定时任务。(类似于王者的技能触发一次后要等CD结束后才能触发下一次)
图片的懒加载
利用scrollTop和img标签距离顶部的高度做对比,给img的src赋值
Cookie、session、token、JWT区别
认证:
认证就是验证当前用户的身份
-
用户密码登录
-
邮箱发送邮件登录
-
手机验证码登录
授权:
授权就是用户授予第三方应用访问该用户某些资源的权限
实现授权的方式:
-
cookie
-
session
-
token
凭证:
实现认证或者授权的前提是需要一种媒介(证书)来标记访问者的身份
-
token
Cookie
-
用户登录以后,服务端会返回浏览器set-cookie,浏览器会存到application的cookie中,下次请求会携带cookie然后去和服务端验证
-
http协议是一个无状态协议,每个请求也是独立的,服务端无法确认当前访问者的身份,也无法分辨这次请求和上次请求是否为同一个人。所以就必须主动维护一个状态,这个状态用于告知服务端是否为同一个人请求的以及来自于同一个浏览器。就需要通过cookie和session去实现
-
cookie存储在客户端,他会在浏览器下次向同一服务器再次发起请求时被携带并发送到服务器上
-
cookie是不可跨域的,每个cookie都会绑定一个单一的域名。一级域名和二级域名是允许共享的(靠的是domain)
Session
-
session是基于cookie实现的
-
session是存于服务端的,sessionId会被存储到客户端的cookie中
-
让http协议有状态
Session认证流程
-
用户第一次请求服务器的时候,服务区会根据用户提交的相关信息,创建对应的session
-
请求返回时将此Session对应的唯一sessionId返回给浏览器
-
浏览器接收sessionId之后,会将此信息存入到Cookie中,同时Cookie记录此SessionId属于哪个域名
-
当用户下次访问服务器的时候,请求会自动判断此域名下是否存在cookie信息,如果存在自动将Cookie发送到服务端,服务端会从cookie中获取sessionId,并用来查找对应的session,如果找到则证明用户已经登录并且可以执行后面操作。如果没有找到则说明用户登录失效,或者没有登录。
token(令牌)
-
访问资源接口(API)时需要的资源凭证
-
token组成:uid(用户唯一身份标识)、time(时间戳)、sign(签名)
-
特点:服务端无状态化、可扩展性好。支持移动端设备。安全。支持跨程序调用
token的身份验证流程:
-
客户端使用账号密码登录
-
服务端收到请求去验证账号密码
-
成功之后,服务端会签发一个token,并且把token发送给客户端
-
客户端接收到token以后,会把她存储起来,比如放在cookie中或者localstroage中
-
客户端每次发起http请求的时候都会带上服务端签发的token
-
服务端接收后去验证里面的token,验证成功,服务端返回请求的数据
-
每一次携带token就会放到http的header里面(通常做封装处理)
-
基于token的用户认证是一种服务端无状态的认证方式,服务端无须存储token。解析token的时间来换取session的存储空间,从而减轻服务器的压力,减少频繁的查询
-
token完全由应用管理,可以避开同源策略
token和session、cookie的区别
-
session和cookie是让http协议有状态,而token不会
-
token可以避开同源策略
-
token安全性会比session好,每次请求都会有签名
-
如果用户数据和第三方共享,或者允许第三方调用API接口,用token
JWT
JSON WEB TOKEN(JWT),是目前最流行的跨域认证解决方案。是一种认证授权机制
Token和JWT的区别
相同:
-
都是访问资源的令牌
-
都可以记录用户的信息
-
服务端无状态化
-
验证成功之后,客户端才能访问服务端上受保护的资源
不同:
-
token是服务端验证客户端发送的,还需要查询数据库获取用户信息,然后验证token是否有效
-
将token和payload加密后存储于客户端,服务端只需要使用秘钥解密进行校验(校验也是JWT自己实现的)即可,不需要查询或者减少查询数据库,因为JWT自包含了用户信息和加密的数据