-
浏览器的缓存方法和原理
1、http缓存是基于HTTP协议的浏览器文件级缓存机制。
2、indexDB 是一个为了能够在客户端存储可观数量的结构化数据,并且在这些数据上使用索引进行高性能检索的 API
3、Cookie一般网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密),可以设置过期时间(数据大小不能超过4k)
4、Localstorage html5的一种本地缓存方案,目前用的比较多,一般用来存储api返回的数据,加快下次页面打开时的渲染速度,用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的(最大到5M)
5、Sessionstorage和localstorage类似,但是浏览器关闭则会全部删除,api和localstorage相同,实际项目中使用较少。(最大到5M)
6、application cache 是将大部分图片资源、js、css等静态资源放在manifest文件配置中
7、cacheStorage是在ServiceWorker的规范中定义的,可以保存每个serverWorker申明的cache对象
-
浏览器缓存的优点
1.减少了冗余的数据传输,节省了网费
2.减少了服务器的负担,大大提升了网站的性能
3.加快了客户端加载网页的速度
浏览器缓存主要有两类:缓存协商和彻底缓存,也有称之为协商缓存和强缓存。
-
强缓存与协商缓存
1.强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network选项中可以看到该请求返回200的状态码;
2.协商缓存:向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源; 两者的共同点是,都是从客户端缓存中读取资源;区别是强缓存不会发请求,协商缓存会发请求 强缓存与协商缓存的区别,可以用下表来进行描述:
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Cache-Control" content="no-cache" />
cache-control可设置值:
• no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
• no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
• public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
• private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
• 浏览器缓存过程
1.浏览器第一次加载资源,服务器返回200,浏览器将资源文件从服务器上请求下载下来,并把response header及该请求的返回时间一并缓存;
2.下一次加载资源时,先比较当前时间和上一次返回200时的时间差,如果没有超过cache-control设置的max-age,则没有过期,命中强缓存,不发请求直接从本地缓存读取该文件(如果浏览器不支持HTTP1.1,则用expires判断是否过期);如果时间过期,则向服务器发送header带有If-None-Match和If-Modified-Since的请求;
3.服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;
4.如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200;
-
cookies,sessionStorage和localstorage区别
相同点:
都存储在客户端
不同点:
1.存储大小 · cookie数据大小不能超过4k。 · sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。(就是为了更大容量的存储设计的) 2.有效时间 · localStorage 存储持久数据(存储在硬盘中,浏览器关闭后数据不丢失除非主动删除数据; · sessionStorage 数据在当前浏览器窗口关闭后自动删除(打开同源窗或刷新浏览器不清除)。 · cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭(未设置过期时间关闭浏览器即清除) 3. 数据与服务器之间的交互方式 · cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端 · sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。 浏览器的同源政策规定,两个网址只要域名和端口相同,就可以共享Cookie,这意味着不同协议的两个网址可以共享Cookie
document.cookie
该属性用于读写当前页面的Cookie,如写入一个cookie:
document.cookie = "foo=bar; expires=Fri, 31 Dec 2020 23:59:59 GMT";
-
谈谈垃圾回收机制方式及内存管理
回收机制方式
1、定义和用法:垃圾回收机制(GC:Garbage Collection),执行环境负责管理代码执行过程中使用的内存。
2、原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。但是这个过程不是实时的,因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行。
3、实例如下:
function fn1() {
var obj = {name: 'hanzichi', age: 10};
}
function fn2() {
var obj = {name:'hanzichi', age: 10};
return obj;
}
var a = fn1();
var b = fn2();
fn1中定义的obj为局部变量,而当调用结束后,出了fn1的环境,那么该块内存会被js引擎中的垃圾回收器自动释放;在fn2被调用的过程中,返回的对象被全局变量b所指向,所以该块内存并不会被释放。
垃圾回收策略:标记清除(较为常用)和引用计数。
- 标记清除:
定义和用法:当变量进入环境时,将变量标记"进入环境",当变量离开环境时,标记为:"离开环境"。某一个时刻,垃圾回收器会过滤掉环境中的变量,以及被环境变量引用的变量,剩下的就是被视为准备回收的变量。
到目前为止,IE、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。
- 引用计数:
定义和用法:引用计数是跟踪记录每个值被引用的次数。
基本原理:就是变量的引用次数,被引用一次则加1,当这个引用计数为0时,被视为准备回收的对象。
-
浏览器的内核分别是什么
浏览器内核使用navigator.userAgent获取
IE: trident内核
Firefox:gecko内核
Safari:webkit内核
Opera:以前是presto内核,Opera现已改用Google Chrome的Blink内核
Chrome:Blink(基于webkit,Google与Opera Software共同开发)
-
浏览器是如何渲染页面的
1.解析HTML文件,创建DOM树。 自上而下,遇到任何样式(link、style)与脚本(script)都会阻塞(@import的外部样式不阻塞后续外部脚本的加载)。 2.解析CSS。优先级:浏览器默认设置<用户设置<外部样式<内联样式<HTML中的style样式; 3.将CSS与DOM合并,构建渲染树(Render Tree) 4.布局和绘制,重绘(repaint)和重排(reflow)
-
内存泄漏
内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束。即指由于疏忽或错误造成程序未能释放已经不再使用的内存。 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。 内存泄露会导致一系列问题,比如:运行缓慢,崩溃,高延迟,甚至一些与其他应用相关的问题。 原因:
1)意外的全局变量引起的内存泄露
function leak(){
leak="xxx";//leak成为一个全局变量,不会被回收
}
2)闭包引起的内存泄露
3)没有清理的DOM元素引用
4)被遗忘的定时器或者回调
5)子元素存在引起的内存泄露
-
浏览器的事件机制:
javaScript 事件循环机制分为浏览器和 Node 事件循环机制,两者的实现技术不一样,浏览器 Event Loop 是 HTML 中定义的规范,Node Event Loop 是由 libuv 库实现。这里主要讲的是浏览器部分。 Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。
• JS 调用栈
JS 调用栈是一种后进先出的数据结构。当函数被调用时,会被添加到栈中的顶部,执行完成之后就从栈顶部移出该函数,直到栈内被清空。
• 同步任务、异步任务
JavaScript 单线程中的任务分为同步任务和异步任务。同步任务会在调用栈中按照顺序排队等待主线程执行,异步任务则会在异步有了结果后将注册的回调函数添加到任务队列(消息队列)中等待主线程空闲的时候,也就是栈内被清空的时候,被读取到栈中等待主线程执行。任务队列是先进先出的数据结构。
• Event Loop事件循环
调用栈中的同步任务都执行完毕,栈内被清空了,就代表主线程空闲了,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。每次栈内被清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作,就形成了事件循环。
• 定时器
定时器会开启一条定时器触发线程来触发计时,定时器会在等待了指定的时间后将事件放入到任务队列中等待读取到主线程执行。
定时器指定的延时毫秒数其实并不准确,因为定时器只是在到了指定的时间时将事件放入到任务队列中,必须要等到同步的任务和现有的任务队列中的事件全部执行完成之后,才会去读取定时器的事件到主线程执行,中间可能会存在耗时比较久的任务,那么就不可能保证在指定的时间执行。
• 宏任务(macro-task)、微任务(micro-task)
除了广义的同步任务和异步任务,JavaScript 单线程中的任务可以细分为宏任务和微任务。
macro-task包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver。
-
浏览器内核线程管理
○ 浏览器是多线程的,每一个tab是一个独立的进程(但空白tab会合并到一个进程里)
○ 浏览器内核有多种线程在工作。
• **GUI 渲染线程**:
○ 负责渲染页面,解析 HTML,CSS 构成 DOM 树等,当页面重绘或者由于某种操作引起回流都会调起该线程。
○ 和 JS 引擎线程是互斥的,当 JS 引擎线程在工作的时候,GUI 渲染线程会被挂起,GUI 更新被放入在 JS 任务队列中,等待 JS 引擎线程空闲的时候继续执行。
• **JS 引擎线程**:
○ 单线程工作,负责解析运行 JavaScript 脚本。
○ 和 GUI 渲染线程互斥,JS 运行耗时过长就会导致页面阻塞。
• **事件触发线程**:
○ 当事件符合触发条件被触发时,该线程会把对应的事件回调函数添加到任务队列的队尾,等待 JS 引擎处理。
• **定时器触发线程**:(宏任务)
○ 浏览器定时计数器并不是由 JS 引擎计数的,阻塞会导致计时不准确。
○ 开启定时器触发线程来计时并触发计时,计时完成后会被添加到任务队列中,等待 JS 引擎处理。
• **http 请求线程**:
○ http 请求的时候会开启一条请求线程。
○ 请求完成有结果了之后,将请求的回调函数添加到任务队列中,等待 JS 引擎处理。