常见操作数组、字符串 API
- 字符串
API 定义 用法 slice(start, end) 用于提取字符串中介于两个指定下标之间的字符,包前不包后,返回新的 str,不改变原 str start,必需。end 可选。均可为负数 substring(start, end) 用于提取字符串中介于两个指定下标之间的字符,包前不包后,返回新的 str,不改变原 str start,必需,非负整数。end 可选,非负整数,如果省略该参数,那么返回的子串会一直到字符串的结尾。 substr(start, length) 在字符串中抽取从 start 下标开始的指定数目的字符,返回新的 str,不改变原 str start 必需,要抽取的子串的起始下标,必须是数值。length 可选,子串中的字符数,必须是数值。如果省略了该参数,那么返回从 str 的开始位置到结尾的字串。 slice(start, end) 和 substring(start, end) 类似,都是返回一个 (start, end] 区间的字符串。唯一不同需要注意的情况是,如果 x>y 的情况发生,slice 会产生一个空字符串,而 Substring 会自动调换位置,等同于 substring(y, x) 。
toLowerCase
toUpperCase
- 数组
API 定义 用法 splice(index, howmany, item1,....., itemX) 向/从数组中添加/删除项目,返回被删除的项目,改变原始数组 index,必需,规定添加/删除项目的位置。howmany,必需,要删除的项目数量。如果设置为 0,则不会删除项目。item1, ..., itemX,可选。向数组添加的新项目。 slice(start, end) 从已有的数组中返回选定的元素,包前不包后,返回新的 数组,不改变原始数组 start,必需。规定从何处开始选取。end,可选,规定从何处结束选取,如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。 pop() 删除并返回数组的最后一个元素,改变原始数组 push() 向数组的末尾添加一个或更多元素,并返回新的长度,改变原始数组。 shift() 删除并返回数组的第一个元素,改变原始数组 unshift() 向数组的开头添加一个或更多元素,并返回新的长度,改变原始数组。 concat() 连接两个或更多的数组,并返回结果,不改变原始数组 join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔,不改变原始数组。
判断数据类型
-
typeof
:typeof 只能检测基本数据类型,包括 boolean、undefined、string、function、symbol,而 null、Array、Object,使用 typeof 出来都是 object。
typeof 构造函数 === 'function'
typeof 构造函数的实例 === 'object' -
instanceof
:instanceof 只能用来判断对象类型 Array、Object -
constructor
:返回创建实例对象的 Object 构造函数的引用 -
Object.prototype.toString.call()
:返回 [object type] ,其中 type 为对象的类型
事件委托
JavaScript 创建动态页面。事件是可以被 JavaScript 侦测到的行为。 网页中的每个元素都可以产生某些可以触发 JavaScript 函数或程序的事件。
事件委托,又叫事件代理。事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
事件冒泡,就是事件从最深的节点开始,然后逐步向上传播事件。直观而言就是对于某个子元素的点击事件同样会被父元素的点击事件处理器捕获。避免 Event Bubbling
的方式可以使用 event.stopPropagation()
,或者 IE9 以下使用 event.cancelBubble = true
。
事件捕获,是先由最上一级的节点先接收事件,然后向下传播到具体的节点。
addEventListener('eventType', 'handler', 'true | false')
eventType 指事件类型,注意不要加‘on’前缀,与IE下不同。handler 是处理函数。第三个参数为 boolean 值,如果为 true,则事件处理函数将在事件传播的捕获阶段触发;如果为 false,则事件处理函数将在冒泡阶段触发。一般设为 false 来与 IE 保持一致(默认设置)。
IE 绑定事件attachEvent(eventType, handler)
、detachEvent(eventType, handler)
JavaScript中的 Event Loop(事件循环)机制
可参考:https://segmentfault.com/a/1190000022805523
构造函数、this 指向、函数防抖和节流
函数防抖:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次。如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
function debounce(fn, wait, immediate) {
let timer = null;
// 返回一个函数
return function(...args) { // 匿名函数没有直接调用者,this 指向 window
// 每次触发事件时都取消之前的定时器
clearTimeout(timer);
// 判断是否要立即执行一次
if(immediate && !timer) {
fn.apply(this, args);
}
// setTimeout 中使用箭头函数,就是让 this 指向上下文函数 this 的指向
timer = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
函数节流:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
function throttle(fn, wait) {
// 设置一个定时器
let timer = null;
return function(...args) {
// 判断如果标记不存在就执行,存在则不执行
if(!timer) {
// 设置下一个定时器
timer = setTimeout(() => {
// 然后执行函数,清除标记
timer = null;
fn.apply(this, args)
}, wait)
}
}
}
// 第一次事件不会触发(fn是放在 setTimeout中执行的,所以第一次触发事件至少等待 wait 毫秒之后才执行),最后一次一定触发
URL组成部分详解
可参考:https://www.cnblogs.com/Bree/p/12009001.html
实现Promise
Promise 是 ES6 提供的一种异步解决方案,比回调函数更加清晰明了。
所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
function myPromise(constructor) {
let self = this;
self.status = 'pending' // 定义状态改变前的初始状态
self.value = undefined; // 定义状态为resolved的时候的状态
self.reason = undefined; // 定义状态为rejected的时候的状态
// 存储回调函数
self.onFulfilledCallbacks = [];
self.onRejectedCallbacks = [];
function resolve(value) {
if (self.status === 'pending') {
self.value = value;
self.status = 'resolved';
self.onFulfilledCallbacks.forEach(function(fulfilledCallback) {
fulfilledCallback();
});
}
}
function reject(reason) {
if (self.status === 'pending') {
self.reason = reason;
self.status = 'rejected';
self.onRejectedCallbacks.forEach(function(rejectedCallback) {
rejectedCallback();
});
}
}
// 捕获构造异常
try {
constructor(resolve, reject);
} catch (e) {
reject(e);
}
}
myPromise.prototype.then = function(onFullfilled, onRejected) {
let self = this;
switch (self.status) {
case 'resolved':
onFullfilled(self.value);
break;
case 'rejected':
onRejected(self.reason);
break;
case 'pending':
self.onFulfilledCallbacks.push(() => {
onFullfilled(self.value);
});
self.onRejectedCallbacks.push(() => {
onRejected(self.reason);
});
break;
default:
}
}
new myPromise((resolve) => {
console.log(1);
setTimeout(() => {
console.log(2);
resolve(3)
}, 2000);
}).then(value => console.log(value))
new myPromise((resolve) => {
console.log(4);
resolve(5)
}).then(value => console.log(value))
Set、WeakSet、Map、WeakMap
可参考:https://es6.ruanyifeng.com/#docs/set-map
-
Set:
成员唯一、无序且不重复。[value, value],键值与键名是一致的(或者说只有键值,没有键名)。
可以遍历,方法有:add、delete、has。相等比较算法:
-
==
: -
===
: -
SameValue
:如Object.is()
Object.is(NaN, NaN) // true Object.is(0, -0) // false
-
SameValueZero
:如includes
、Set
const a = [0, NaN] a.includes(-0) // true a.includes(NaN) // true
-
-
WeakSet:
成员都是对象。成员都是弱引用,可以被垃圾回收机制回收,可以用来保存 DOM 节点,不容易造成内存泄漏。不能遍历,方法有add、delete、has。 -
Map:
本质上是键值对的集合,类似集合。可以遍历,方法很多可以跟各种数据格式转换。 -
WeakMap:
只接受对象作为键名(null 除外),不接受其他类型的值作为键名。
键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的。不能遍历,方法有 get、set、has、delete。
es 新特性
从输入 URL 到页面展示发生了什么?
DNS域名解析查找域名的 IP 地址、建立TCP链接、发送http请求、服务器处理请求、返回响应结果、关闭TCP连接、浏览器解析HTML、浏览器布局渲染
三次握手:
第一次握手:客户端向服务端发送连接请求报文段,服务端收到了。
服务端得出结论:客户端的发送能力、服务端的接收能力正常。
第二次握手:服务端收到连接请求报文段后,如果同意连接,则会向客户端发送一个应答。
客户端得出结论:服务端的接收、发送能力,客户端的接收、发送能力正常。不过此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。
服务端得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
因此,需要三次握手才能确认双方的接收与发送能力是否正常。
四次挥手:
第一次挥手:客户端发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。
第二次挥手:服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。
第三次挥手:服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。
第四次挥手:客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。
HTML、CSS 和 JavaScript,是如何变成页面的?
实现拷贝
数组扁平化 + 去重 + 排序
Array.from(new Set(arr.flat(Infinity))).sort((a, b) => { return a - b})
正则替换日期格式
var reg = /(\d{2})\.(\d{2})\/(\d{4})/
var data = '10.24/2017'
data = data.replace(reg, '$3-$1-$2')
console.log(data) // 2017-10-24
面向对象的思想、核心
面向对象,在基于对象的基础上增加了多态性。
所谓多态,就是可以用统一的方法对不同的对象进行同样的操作。当然,这些对象不能完全不同,而需要有一些共性,只有存在了这些共性才可能用同样的方法去操作它们。
-
面向对象的三个基本特征是:封装、继承、多态。
- 封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
- 继承:可以让某个类型的对象获得另一个类型的对象的属性的方法。通过继承创建的新类称为“子类”或“派生类”。被继承的类称为“基类”、“父类”或“超类”。
- 多态:一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。
- 封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
-
面向对象五大基本原则
- 单一职责原则:一个类的功能要单一,不能包罗万象
- 开放封闭原则:一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的
- 替换原则:子类应当可以替换父类并出现在父类能够出现的任何地方
- 依赖原则:具体依赖抽象,上层依赖下层
- 接口分离原则:模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来
JS类型转换
可参考:https://zhuanlan.zhihu.com/p/256392595
String([]) // ""
String({}) // "[object Object]"
Number({}) // NaN
Number([]) // 0
parseFloat('01.2.4') // 1.2
const a = 1
console.log(typeof a) // number
console.log(typeof new Number(a)) // object
网站如何监听你切换到了其他页面?
// 监听 docuemnt.vibibleChange 事件
document.addEventListener("visibilitychange", function() {
console.log( document.hidden );
});
0.1 + 0.2 = 0.3
吗?
计算机的二进制实现和位数限制有些数无法有限表示。就像一些无理数不能有限表示,如 圆周率 3.1415926...,1.3333... 等。JS 遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit。
由于0.1转换成二进制时是无限循环的,所以在计算机中0.1只能存储成一个近似值。除了那些能表示成 x/2^n 的数可以被精确表示以外,其余小数都是以近似值得方式存在的。
在0.1 + 0.2这个式子中,0.1和0.2都是近似表示的,在他们相加的时候,两个近似值进行了计算,导致最后得到的值是0.30000000000000004,此时对于JS来说,其不够近似于0.3,于是就出现了0.1 + 0.2 != 0.3 这个现象。 当然,也并非所有的近似值相加都得不到正确的结果。
有时两个近似值进行计算的时候,得到的值是在JS的近似范围内的,于是就可以得到正确答案。
所以,要解决类似问题,方法很简单,将浮点数转化成整数来计算就可以解决精度丢失问题了。
什么是闭包、闭包的应用场景
可参考:https://segmentfault.com/a/1190000023356598、https://segmentfault.com/a/1190000023425946
-
概念:
闭包就是能够读取其他函数内部变量的函数。由于在Javascript
语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。 -
用处:
- 可以读取函数内部的变量
- 让这些变量的值始终保持在内存中
-
使用场景:
- 使用闭包代替全局变量
- 函数外或在其他函数中访问某一函数内部的参数
- 在函数执行之前为函数提供只有在函数执行或引用时才能知道的具体参数
- 为节点循环绑定
click
事件,在事件函数中使用当次循环的值或节点,而不是最后一次循环的值或节点 - 暂停执行
- 包装相关功能
-
使用闭包的注意点:
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在
IE
中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除(手动将变量设置为null
,该变量将因为无引用被自动回收)。 - 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(
object
)使用,把闭包当作它的公用方法(Public Method
),把内部变量当作它的私有属性(private value
),这时一定要小心,不要随便改变父函数内部变量的值。
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在
怎样理解阻塞非阻塞与同步异步的区别?
同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)
所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。
而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
内存溢出(out of memory) && 内存泄露(memory leak)
内存溢出:指程序在申请内存时,没有足够的内存空间供其使用,出现溢出。
内存泄露:指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak
会最终会导致 out of memory
!
- 内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
- 内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问,而系统也不能再次将它分配给需要的程序。分配的内存不足以放下数据项序列,称为内存溢出。
- 内存泄漏的原因:
- 未定义的变量会在全局对象创建一个新变量。在
JS
文件头部加上'use strict'
,可以避免意外的全局变量。 - 当页面中元素被移除或替换时,若元素绑定的事件仍没被移除,在
IE
中不会作出恰当处理,此时要先手工移除事件,不然会存在内存泄露。 - 闭包可以维持函数内局部变量,使其得不到释放
- 未定义的变量会在全局对象创建一个新变量。在
- 内存溢出的原因:
- 内存中加载的数据量过于庞大,如一次从数据库取出过多数据(采用分页的方式查询);
- 代码中存在死循环或递归调用或循环产生过多重复的对象实体;
RESTful API 设计指南
- 协议:
API
与用户的通信协议,总是使用HTTPS
协议。 - 域名:尽量将
API
部署在专用域名之下https://api.example.com
。如果确定API
很简单,不会有进一步扩展,可以考虑放在主域名下https://example.org/api/
- 版本(Versioning):将
API
的版本号放入URL
https://api.example.com/v1/
。另一种做法是,将版本号放在HTTP
头信息中,但不如放入URL
方便和直观。Github
采用这种做法。 - 路径(
Endpoint
),"终点"(endpoint
),表示API
的具体网址。
在RESTful
架构中,每个网址代表一种资源(resource
),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection
),所以API
中的名词也应该使用复数。举例来说,有一个API
提供动物园(zoo
)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样:https://api.example.com/v1/zoos、https://api.example.com/v1/animals、https://api.example.com/v1/employees
。 -
HTTP
动词:对于资源的具体操作类型,由HTTP
动词表示。- 常用的
HTTP
动词有下面五个(括号里是对应的SQL
命令)。-
GET
(SELECT
):从服务器取出资源(一项或多项),get /zoos:列出所有动物园
、get /zoos/ID:获取某个指定动物园的信息
、get /zoos/ID/animals:列出某个指定动物园的所有动物
。 -
POST
(CREATE
):在服务器新建一个资源,post /zoos:新建一个动物园
。 -
PUT
(UPDATE
):在服务器更新资源(客户端提供改变后的完整资源),put /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
。 -
PATCH
(UPDATE
):在服务器更新资源(客户端提供改变的属性),patch /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
。 -
DELETE
(DELETE
):从服务器删除资源,delete /zoos/ID:删除某个动物园
、delete /zoos/ID/animals/ID:删除某个指定动物园的指定动物
。
-
- 还有两个不常用的HTTP动词。
-
HEAD
:获取资源的元数据。 -
OPTIONS
:获取信息,关于资源的哪些属性是客户端可以改变的。
-
- 常用的
- 过滤信息(
Filtering
):如果记录数量很多,服务器不可能都将它们返回给用户。API
应该提供参数,过滤返回结果。- 下面是一些常见的参数。
-
?limit=10
:指定返回记录的数量。 -
?offset=10
:指定返回记录的开始位置。 -
?page=2&per_page=100
:指定第几页,以及每页的记录数。 -
?sortby=name&order=asc
:指定返回结果按照哪个属性排序,以及排序顺序。 -
?animal_type_id=1
:指定筛选条件 - 参数的设计允许存在冗余,即允许
API
路径和URL
参数偶尔有重复。比如,GET /zoo/ID/animals
与GET /animals?zoo_id=ID
的含义是相同的。
-
- 下面是一些常见的参数。
- 状态码(
Status Codes
):服务器向用户返回的状态码和提示信息- 常见的有以下一些(方括号中是该状态码对应的HTTP动词)。
-
200 OK - [GET]
:服务器成功返回用户请求的数据。 -
201 CREATED - [POST/PUT/PATCH]
:用户新建或修改数据成功。 -
202 Accepted - [*]
:表示一个请求已经进入后台排队(异步任务) -
204 NO CONTENT - [DELETE]
:用户删除数据成功。 -
400 INVALID REQUEST - [POST/PUT/PATCH]
:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。 -
401 Unauthorized - [*]
:表示用户没有权限(令牌、用户名、密码错误)。 -
403 Forbidden - [*]
:表示用户得到授权(与401
错误相对),但是访问是被禁止的。 -
404 NOT FOUND - [*]
:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 -
406 Not Acceptable - [GET]
:用户请求的格式不可得(比如用户请求JSON
格式,但是只有XML
格式)。 -
410 Gone -[GET]
:用户请求的资源被永久删除,且不会再得到的。 -
422 Unprocesable entity - [POST/PUT/PATCH]
: 当创建一个对象时,发生一个验证错误。 -
500 INTERNAL SERVER ERROR - [*]
:服务器发生错误,用户将无法判断发出的请求是否成功。
-
- 常见的有以下一些(方括号中是该状态码对应的HTTP动词)。
- 错误处理(
Error handling
):如果状态码是4xx
,就应该向用户返回出错信息。
一般来说,返回的信息中将error
作为键名,出错信息作为键值即可。{ error: "Invalid API key" }
cookie 和 session 的区别详解
- 通常请求和响应称为会话,所以有时也会说
cookie
和session
是用来维持会话状态的。cookie
是记录在客户端(浏览器)通过document.cookie
进行读写。
console.log(document.cookie); // 读取,cookie 是以字符串形式存在的
document.cookie = 'age=28'; // 设置
-
cookie
默认生命周期为关闭浏览器,也可以进行设置
document.cookie = 'name=xiaoming; expires=' + (new Date('2017-12-31')).toUTCString();
-
cookie
数据存放在客户的浏览器上,session
数据放在服务器上。 -
cookie
不是很安全,别人可以分析存放在本地的COOKIE
并进行COOKIE
欺骗,考虑到安全应当使用session
。 -
session
会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE
。 - 单个
cookie
保存的数据不能超过4K
,很多浏览器都限制一个站点最多保存20个cookie
。 - 要实现用户登录功能就必须要记录用户登录状态,配合
cookie
和session
可以解决这个问题:- 用户输入正确用户名和密码后,将登录信息存储在
cookie
中,每次请求会将这个存储的信息发送到服务器,通过检测这个信息判断用户是否已登录,由于cookie
是记录在客户端(浏览器)的,所以安全性不好。 - 用户输入正确用户名和密码后,将登录信息存储在
session
中,由于session
是存储在服务端,所以安全性很好,但是可能会带来另外一个问题,即服务器不能明确知道所存储的session
信息是属于哪一个客户端(浏览器)。实际上是通过cookie
来解决这个问题的,具体实现过程是服务器在存储session
信息后,会生成一个唯一标识(sessionid
)并将这个标识响应给浏览器,浏览器将这个标识(sessionid
)存储在cookie
中,当下次再请求时浏览器会将这个标识(sessionid
)传递给服务端,服务端利用这个标识找到对应的session
,进而判断用户的登录情况。
- 用户输入正确用户名和密码后,将登录信息存储在
sessionStorage、localStorage
-
sessionStorage
:会话存储- 生命周期:页面关闭,数据丢失
- 只能在同一窗口共享数据,存储大小为
5M
-
localStorage
:本地存储,存储在硬盘上- 生命周期:永久生效,除非手动删除
- 多个窗口共享数据,存储大小为
20M
-
sessionStorage 、localStorage 、cookie
之间的区别- 共同点:都是保存在浏览器端,且同源的。
- 区别:
-
cookie
数据始终在同源的http
请求中携带(即使不需要),即cookie
在浏览器和服务器间来回传递。而sessionStorage
和localStorage
不会自动把数据发给服务器,仅在本地保存。cookie
数据还有路径(path
)的概念,可以限制cookie
只属于某个路径下。 - 存储大小限制也不同,
cookie
数据不能超过4k
,同时因为每次http
请求都会携带cookie
,所以cookie
只适合保存很小的数据,如会话标识。sessionStorage
和localStorage
虽然也有存储大小的限制,但比cookie
大得多,可以达到5M
或更大。 - 数据有效期不同,
sessionStorage
:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage
:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie
只在设置的cookie
过期时间之前一直有效,即使窗口或浏览器关闭。 - 作用域不同,
sessionStorage
不在不同的浏览器窗口中共享,即使是同一个页面;localStorage
在所有同源窗口中都是共享的;cookie
也是在所有同源窗口中都是共享的。 -
Web Storage
支持事件通知机制,可以将数据更新的通知发送给监听者。 -
Web Storage
的api
接口使用更方便。
-
基本数据类型
可参考:https://blog.csdn.net/yiyueqinghui/article/details/106783798
网友评论