1.内存泄漏与垃圾回收
2.cookie和session
3.单线程原理
4.上下左右居中的几种实现。
5.BFC和IFC模型。
参考:内存控制css
v8的垃圾回收策略主要基于分代式垃圾回收机制。按照对象的存活时间将内存的垃圾回收进行不一样的分代,而后,分别对不一样的分代的内存再进行高效的垃圾回收算法。在V8中,主要将内存分为新生代和老生代两代。新内存中的对象存活时间短,老内存中的对象存活时间长或常驻内存对象。html
1)新生代垃圾回收算法scavenge算法java
新生代中的对象主要经过scavenge算法进行垃圾回收,其主要是采用cheney算法进行具体处理。web
cheney算法采用一种复制方式的垃圾回收算法,将堆内存一分为二,只有一部分空间被使用称为From空间,另外一个处于闲置称为To空间。当进行分配对象的时候先在from空间分配,当进行垃圾回收时,会检查from空间中的存活对象,将这些存活对象复制到to空间中,复制完成后From和to空间角色互换,清空to空间,在垃圾回收过程当中就是经过将存活对象在两个空间中进行复制。ajax
当一个对象通过屡次复制依然存活时,就会被认为是生命周期较长的对象,会被移入老生代内存中。算法
对于移入老生代内存有两个条件:segmentfault
2)老内存垃圾回收算法Mark-Sweep & Mark-Compactapi
老内存中,大可能是不死的老对象,用scavenge算法又费力,又占用空间,所以,采用了新的内存垃圾回收算法:Mark-Sweep & Mark-Compact。数组
Mark-Sweep 标记清扫浏览器
mark-sweep分为标记和清除两个阶段,mark阶段会遍历堆,而后标记处活着的对象,sweep阶段会清除没有被标记的对象。mark-sweep只清理没有标记的对象,在老内存中,死了的对象占比较少,这也是这个算法高效的缘由。
mark-sweep的问题在于,每次sweep后,会存在内存碎片,这些不连续的内存碎片会占有大量空间,所以,下一次复制大对象时,将会发现空间不够,于是再次触发垃圾回收,这个回收是没必要要的,也浪费了cpu。为了解决这个问题,增长了mark-compact算法。
mark-compact 标记整理和压缩
mark-compact在整理过程当中,将活着的对象往一端移动,移动完成后,直接将另一端的内存清理掉。
由于mark-compact须要移动内存,所以,垃圾回收主要使用mark-sweep,在内存不够时,才会触发一次mark-compact。
这三种算法的比较:
Incremental Marking
为了不出现javaScript应用逻辑与垃圾回收器看到不一致的状况,垃圾回收都要将应用逻辑停下来,这种行为会形成停顿,在新生代垃圾回收过程当中由于存活对象比较少,即便停顿基本影响不大。在老生代垃圾回收中,一般存活对象较多,全堆垃圾回收的标记、清除、整理影响较大。
解决办法:分批次进行,拆分红许多小步,每进行一小步就让逻辑运行一会。
v8后续还引入了lazy sweeping与incremental compaction,同时还引入了,并行标记和并行清理,进一步的利用多核性能下降每次停顿的时间。
内存泄漏的实质就是应当回收的对象由于意外没有被回收,变成了常驻在老生代中的对象。
形成内存泄漏的主要缘由有:缓存、队列消费不及时、做用域未释放。
1)缓存
慎将内存当作缓存,一旦一个对象被当作缓存来使用,那它将会常驻在老生代中,这将致使垃圾回收在进行扫描和整理时,对这些对象作无用功。
v8内存是经过垃圾回收进行处理的,没有过时策略,而真正的缓存是存在过时策略的。
缓存限制策略:将结果记录在数组中,一旦超过数量,就以先进先出的方式进行淘汰。
2)闭包
闭包是经过中间函数进行间接访问内部变量实现的一个功能,一旦变量引用这个中间函数,这个中间函数将不会释放,同时也会使原始的做用域不会获得释放,做用域中产生的内存占用也不会获得释放。除非再也不有引用,才会逐步释放。
参考:构建Web应用
http是一个无状态的协议,现实中的业务倒是须要有状态的,不然没法区分用户之间的身份。利用cookie记录浏览器与客户端之间的状态。
cookie的处理分为以下几步:
告知客户端是经过响应报文实现的,响应的cookie值在set-cookie字段中,它的格式与请求中的格式不太相同,规范中对它的定义以下:
Set-Cookie: name=value; Path=/; Expires=Sun, 23-Apr-23 09:01:35 GMT; Domain=.domain.com;
name = value是必选字段,其余为可选字段。
可选字段 | 说明 |
---|---|
path | 表示这个cookie影响的路径,当前访问的路径不知足该匹配时,浏览器则不发送这个cookie |
Expires、Max-Age | 用来告知浏览器这个cookie什么时候过时的,若是不设置该选项,在关闭浏览器时,会丢失掉这个cookie,若是设置过时时间,浏览器将会把cookie内容写入到磁盘中,并保存,下次打开浏览器,该cookie依旧有效。expires是一个utc格式的时间字符串,告知浏览器此cookie什么时候将过时,max-age则告知浏览器,此cookie多久后将过时。expires会在浏览器时间设置和服务器时间设置不一致时,存在过时误差。所以,通常用max-age会相对准确。 |
HttpOnly | 告知浏览器不容许经过脚本document.cookie去更改这个cookie值,也就是document.cookie不可见,可是,在http请求的过程当中,依然会发送这个cookie到服务器端。 |
secure | 当secure = true时,建立的cookie只在https链接中,被浏览器传递到服务器端进行会话验证,若是http链接,则不会传递。所以,增长了被窃听的难度。 |
cookie的性能影响
当cookie过多时,会致使报文头较大,因为大多数cookie不须要每次都用上,所以,除非cookie过时,不然会形成带宽的浪费。
cookie优化的建议:
减少cookie的大小,切记不要在路由根节点设置cookie,由于这将形成该路径下的所有请求都会带上这些cookie,同时,静态文件的业务不关心状态,所以,cookie在静态文件服务下,是没有用处,请不要为静态服务设置cookie。
为静态组件使用不一样的域名,cookie做用于相同的路由,所以,设定不一样的域名,能够防止cookie被上传。
减小dns查询,这个能够基于浏览器的dns缓存来削弱这个反作用的影响(换用额外域名须要DNS查询)。
cookie的不安全性
cookie能够在浏览器端,经过调用document.cookie来请求cookie并修改,修改以后,后续的网络请求中就会携带上修改事后的值。
例如:第三方广告或者统计脚本,将cookie和当前页面绑定,这样能够标识用户,获得用户浏览行为。
cookie存在各类问题,例如体积大、不安全,为了解决cookie的这些问题,session应运而生,session只保存在服务器端,客户端没法修改,所以,安全性和数据传递都被保护。
如何将每一个客户和服务器中的数据一一对应:
安全性
session的口令保存在浏览器(基于cookie或者查询字符串的形式都是将口令保存于浏览器),所以,会存在session口令被盗用的状况。当web应用的用户十分多,自行设计的随机算法的口令值就有理论机会命中有效的口令值。一旦口令被伪造,服务器端的数据也可能间接被利用,这里提到的session的安全,就主要指如何让这一口令更加安全。
有一种方法是将这个口令经过私钥加密进行签名,使得伪造的成本较高。客户端尽管能够伪造口令值,可是因为不知道私钥值,签名信息很难伪造。如此,咱们只要在响应时将口令和签名进行对比,若是签名非法,咱们将服务器端的数据当即过时便可,
将口令进行签名是一个很好的解决方案,可是若是攻击者经过某种方式获取了一个真实的口令和签名,他就能实现身份的伪造了,一种方案是将客户端的某些独有信息与口令做为原值,而后签名,这样攻击者一旦不在原始的客户端上进行访问,就会致使签名失败。这些独有信息包括用户IP和用户代理。
JavaScript的单线程,与它的用途有关。做为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操做DOM。这决定了它只能是单线程,不然会带来很复杂的同步问题。好比,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另外一个线程删除了这个节点,这时浏览器应该以哪一个线程为准?
因此,为了不复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,未来也不会改变。
为了利用多核CPU的计算能力,HTML5提出Web Worker标准,容许JavaScript脚本建立多个线程,可是子线程彻底受主线程控制,且不得操做DOM。因此,这个新标准并无改变JavaScript单线程的本质。
全部任务能够分红两种,一种是同步任务(synchronous),另外一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务能够执行了,该任务才会进入主线程执行。
异步执行的运行机制以下。(同步执行也是如此,由于它能够被视为没有异步任务的异步执行。)
js引擎执行异步代码而不用等待,是因有为有 消息队列和事件循环。
消息队列:消息队列是一个先进先出的队列,它里面存放着各类消息。
事件循环:事件循环是指主线程重复从消息队列中取消息、执行的过程。
JS中分为两种任务类型:macrotask和microtask,在ECMAScript中,microtask称为jobs,macrotask可称为task。
在挂起任务时,JS 引擎会将全部任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫作 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的全部任务顺序执行;以后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。
宏任务和微任务之间的关系:
事件循环机制进一步补充
1.http://www.ruanyifeng.com/blo...
2.https://www.jianshu.com/p/f47...
3.实例
https://blog.csdn.net/mars200...
BFC(Block Formatting Context)叫作“块级格式化上下文”。
当一个元素设置了新的BFC后,就和这个元素外部的BFC没有关系了,这个元素只会去约束本身内部的子元素。
1)BFC的布局规则以下:
2)如何产生新的BFC
3)实际应用
IFC(Inline Formatting Content)叫作 行内格式化上下文。
1)规则
2)主要影响IFC内布局的css: 参考
容器的高度 height = line-height + vertical-align