1. 垃圾回收机制
(1)栈中的数据:
当前函数执行上下文完成,记录当前执行状态的指针(ESP)下移,当前函数执行上 下文接着被销毁。
(2)堆中的数据:
函数执行上下文被销毁,但上下文中对引用类型的数据存放在堆中的尚未销毁。
- 副垃圾回收器:负责新生代垃圾回收,内存空间较小(1~8M),使用Scavenge算法,将新生代空间划分两个区域,对象区域和空闲区域。新加入的对象都会存放到对象区域,当对象区域快被写满,需要执行一次垃圾清除操作。
垃圾回收过程:
首先要对对象区域中的垃圾做标记;标记完成之后,就进入垃圾清理阶段,副垃圾回收器会把这些存活的对象复制到空闲区域中,同时它还会把这些对象有序地排列起来,所以这个复制过程,也就相当于完成了内存整理操作,复制后空闲区域就没有内存碎片了。完成复制后,对象区域与空闲区域进行角色翻转,也就是原来的对象区域变成空闲区域,原来的空闲区域变成了对象区域。经过两次垃圾回收依然还存活的对象,会被移动到老生区中。
- 主垃圾回收器:负责老生代垃圾回收。除了新生区中晋升的对象,一些大的对象会直接被分配到老生区。
垃圾回收过程:
标记 - 清除(Mark-Sweep):首先是标记过程阶段。标记阶段就是从一组根元素开始,递归遍历这组根元素,在这个遍历过程中,能到达的元素称为活动对象,没有到达的元素就可以判断为垃圾数据。将标记为垃圾数据的进行清除.
标记 - 整理(Mark-Compact):让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
- 全停顿:
执行垃圾回收算法,都需要将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。为了降低老生代的垃圾回收而造成的卡顿,V8 将标记过程分为一个个的子标记过程,同时让垃圾回收标记和 JavaScript 应用逻辑交替进行,直到标记阶段完成,我们把这个算法称为增量标记(Incremental Marking)算法。
2. 内存泄漏
不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。
- 常见导致内存泄漏
(1)意外声明导致全局变量
(2)计时器的引用没有清除
(3)没有及时清理引用(闭包)
3. 同源策略
只被允许访问来自同一站点的资源,同源是指:域名、协议、端口相同。
分为以下两种:
DOM 同源策略:禁止对不同源页面 DOM 进行操作。这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。
XMLHttpRequest 同源策略:禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。
跨域的解决方案
(一)CORS(Cross-origin resource sharing,跨域资源共享),CORS 背后的基本思想,就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。CORS 需要浏览器和服务器同时支持。
首先区分是简单请求还是非简单请求:
简单请求:
-
在请求中需要附加一个额外的 Origin 头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。例如:Origin: www.laixiangran.cn
-
如果服务器认为这个请求可以接受,就在 Access-Control-Allow-Origin 头部中回发相同的源信息(如果是公共资源,可以回发 * )。例如:Access-Control-Allow-Origin:www.laixiangran.cn
-
没有这个头部或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器会处理请求。注意,请求和响应都不包含 cookie 信息。
-
如果需要包含 cookie 信息,ajax 请求需要设置 xhr 的属性 withCredentials 为 true,服务器需要设置响应头部 Access-Control-Allow-Credentials: true。
非简单请求:
浏览器在发送真正的请求之前,会先发送一个 Preflight 请求给服务器,这种请求使用 OPTIONS 方法,发送这个请求后,服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器进行沟通。一旦服务器通过 Preflight 请求允许该请求之后,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样了。
(二)JSONP
由于 script 标签不受浏览器同源策略的影响,允许跨域引用资源。因此可以通过动态创建 script 标签,然后利用 src 属性进行跨域
(三)图像 Ping
由于 img 标签不受浏览器同源策略的影响,允许跨域引用资源。
(四)postMessage
window.postMessage(message,targetOrigin) 方法是 HTML5 新引进的特性,可以使用它来向其它的 window 对象发送消息,无论这个 window 对象是属于同源或不同源。这个应该就是以后解决 dom 跨域通用方法了。
调用 postMessage 方法的 window 对象是指要接收消息的那一个 window 对象,该方法的第一个参数 message 为要发送的消息,类型只能为字符串;第二个参数 targetOrigin 用来限定接收消息的那个 window 对象所在的域,如果不想限定域,可以使用通配符 *。
需要接收消息的 window 对象,可是通过监听自身的 message 事件来获取传过来的消息,消息内容储存在该事件对象的 data 属性中。
(五)window.name + iframe
window 对象有个 name 属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面(不管是相同域的页面还是不同域的页面)都是共享一个 window.name 的,每个页面对 window.name 都有读写的权限,window.name 是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
(六)loaction.hash + iframe
location.hash 方式跨域,是子框架具有修改父框架 src 的 hash 值,通过这个属性进行传递数据,且更改 hash 值,页面不会刷新。但是传递的数据的字节数是有限的。
(七)WebSocket
4. cookie,sessionStorage,localStorage
(1)cookie
用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。cookie机制,弥补HTTP的不足。有两个HTTP头部专门用来设置以及传送cookie的,分别是Set-Cookie和Cookie。Set-Cookie是服务端传给客户端的,用来告诉客户端建立一个Cookie,并且在后续连接服务端的时候,带上这个Cookie;Cookie就是客户端连接服务端的时候,传给服务端的,告诉服务端这属于哪个会话,直到cookie过期之前,每次连接都会传cookie。
限制访问 Cookie
- Secure
只应通过被 HTTPS 协议加密过的请求发送给服务端
- HttpOnly
API 无法访问带有 HttpOnly 属性的cookie;此类 Cookie 仅作用于服务器。例如,例如,持久化服务器端会话的 Cookie 不需要对 JavaScript 可用,而应具有 HttpOnly 属性。此预防措施有助于缓解跨站点脚本(XSS)攻击。
Cookie 的作用域
- Domain 属性
Domain 指定了哪些主机可以接受 Cookie。如果不指定,默认为 {{Glossary("origin")}},不包含子域名。如果指定了Domain,则一般包含子域名。
- Path 属性
Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。
通过Document.cookie"属性可创建新的 Cookie,也可通过该属性访问非HttpOnly标记的Cookie。通过 JavaScript 创建的 Cookie 不能包含 HttpOnly 标志。
localStorage、seesionStorage、cookie的区别
1)大小限制不同:cookie的大小限制为4k,同个domain下不超过20个;localStorage和sessionStorage的大小限制为5M左右。
2)有效期不同:cookie的有效期是通过设置过期时间来决定的,过期时间之前一直有效,即使浏览器关闭。localStorage的有效期是永久的,除非手动删除。sessionStorage仅在当前会话下有效,关闭页面后就删除。
3)和服务器的通信: cookie在每次与服务器通信的时候都会携带在http头中,cookie保存过多,对通信性能会产生影响;localStorage和sessionStorage都不参与和服务器的通信。
4)作用域不同:不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间可以共享相同的 localStorage和cookie(页面属于相同域名和端口),但是不同页面或标签页间无法共享sessionStorage的信息。这里需要注意的是,页面及标签页仅指顶级窗口,如果一个标签页包含多个iframe标签且他们属于同源页面,那么他们之间是可以共享sessionStorage的。
5. 浏览器缓存策略
- 强缓存
expires和cache-control设置,请求头状态码200,资源from memory cache或from disk cache,每次请求先在缓存找,不匹配再发起请求,来自服务端的响应后将请求结果和缓存标识放入浏览器缓存。强缓存判断依据是资源是否超出某个时间或时间段,不关心服务端资源是否更新。
- 协商缓存
Last-Modified和ETag设置,强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。协商缓存生效,返回304和Not Modified。
6. 浏览器渲染过程
7. 事件循环机制
宏任务(macro task):script,setTimeout,setInterval,setImmediate
微任务(micro task):promise.then,MutationObserver
从script开始解析,当前宏任务进入执行栈,遇到宏任务则挂起将回调放入任务队列,遇到微任务则放入微任务队列。当前宏任务解析到结尾时,执行微任务,微任务执行完后按照顺序执行任务队列里的宏任务