前言

本文主要介绍本地存储的基本使用,以及它和 Cookie、SessionStorage 的区别。

简单回顾 Cookie

在 HTML5 之前,本地存储数据一般是通过 Cookie 来完成的。我们可以把 Cookie 理解为一个长度有限的字符串,服务端和客户端都能读写这个字符串,并且每次请求时,都会把 Cookie 发送到服务端。

通常,我们可以利用这个字符串来保存用户名、密码等数据,来实现记住密码、自动登录等功能。

但是,Cookie 本来就不是用来存储数据的,所以会有一些局限性:

  • 存储空间有限,最多也就是几十 K 的大小。
  • 每次请求都发送到服务器,浪费宽带。
  • 使用起来比较麻烦的,需要自己封装操作函数。

本地存储的简单使用

本地存储(LocalStorage)是一种基于键值对的持久化存储方案。“持久化存储”就意味着,如果不手动清除,数据就永远不会过期。

基于键值对的存储方案,使用起来是很方便的。我们可以通过 localStorage.setItem(key, value) 来保存数据。

比如保存一个用户名:

javascript-demo/localstorage.html

localStorage.setItem('name', 'hello')

然后就可以通过 localStorage.getItem(key) 的方式来获取数据:

localStorage.getItem('name') // hello

LocalStorage 还支持直接对 localStorage 对象的属性进行操作来存取数据,效果和 setItemgetItem 是一样的。

localStorage.hi = 'Hi'
console.log(localStorage.hi) // Hi

以上代码等同于:

localStorage.setItem('hi', 'Hi')
console.log(localStorage.getItem('hi')) // Hi

存储对象

本地存储只支持字符串存储,存储任何类型的数据,都会被转换成字符串。

javascript-demo/localstorage-number.html

localStorage.setItem('age', 1024)
console.log(typeof localStorage.getItem('age')) // string

读取完数据后,还要把数据转成 Number 类型,很麻烦。有时候,我们还需要存储复杂的数据结构。不可能像下面那样将对象的属性一个个存储,再一个个读取。

javascript-demo/localstorage-object.html

// 保存对象
let obj = {
    name: 'hello',
    age: 1024
}
localStorage.setItem('name', obj.name)
localStorage.setItem('age', obj.age)
// 读取对象
let newObj = {
    name: localStorage.getItem('name'),
    age: parseInt(localStorage.getItem('age'))
}
console.log(newObj)

这时,我们需要利用 JSON API,来简单封装本地存储。原理是保存数据前,通过 JSON.stringify 把数据转换成 JSON 字符串再保存;读取数据后,通过 JSON.parse 把 JSON 字符串转换成原来的值。

// 简单封装
const storage = {
    set: function (key, value) {
        localStorage.setItem(key, JSON.stringify(value))
    },
    get: function (key) {
        return JSON.parse(localStorage.getItem(key))
    }
}
// 保存对象
let obj = {
    name: 'hello',
    age: 1024
}
storage.set('obj', obj)
// 读取对象
console.log(storage.get('obj'))

这很方便,存取数字类型时也不需要转换了。

storage.set('age', 1024)
console.log(typeof storage.get('age')) // number

API 介绍

一般来说,setItemgetItem 就足够用了。这里大致介绍一下常用的属性和方法,有兴趣的了解一下。

  • localStorage.length:获得存储的键值对的的个数。
  • localStorage.key(n):获得存储的第 n 个元素对的键值(也叫做键名,不要和值搞混了)(下标从 0 开始)。
  • localStorage.getItem(key):获取 key 对应的 value。
  • localStorage.key:获取 key 对应的 value,相当于 getItem。也可以直接赋值,则相当于 setItem
  • localStorage.setItem(key, value):添加键值对到存储。
  • localStorage.removeItem(key):移除键值为 key 的键值对。
  • localStorage.clear():清除所有数据。

LocalStorage VS Cookie

在数据存储方面,Cookie 的不足,也就是本地存储的优势,相对于 Cookie,本地存储的优势在于:

  • 较大的存储空间。虽然 W3C 对存储空间没有限制,但浏览器有。不同的浏览器的限制大小可能不同。IE8 上是 10MB,Chrome 是 5MB(数据源于网络,本人未去证实)。在未来可能会更大。
  • 不用每次请求都发送到服务器,提高请求速度。
  • 足够好用的 API 支持,操作简单。

尽管本地存储功能强大,但它和 Cookie 的分工不同,还无法用来取代 Cookie。

一般来说,Cookie 用来与服务器进行交互,而不是用来存储。而 LocalStorage 仅用来存储。

同源限制

LocalStorage 同样受限于同源策略。不同源之间的数据无法共享。关于同源策略,不懂的可以看我的这篇文章:前端学习笔记 - 跨域

Session Storage

SessionStorage 和 LocalStorage 功能类似,区别仅仅是数据保存时间的不同而已。LocalStorage 是持久存储的,如果不手动清除,数据就永远不会失效。而 SessionStorage 的数据存储在窗口对象中,一旦窗口对象没了(用户关闭浏览器或标签页),数据就会丢失。

我们可以简单地测试一下:

javascript-demo/sessionstorage.html

console.log(sessionStorage.getItem('name'))
sessionStorage.setItem('name', 'hello')
console.log(sessionStorage.getItem('name'))

第一次运行时,控制台输出:

null
hello

刷新一下浏览器,控制台输出:

hello
hello

然后打开一个新标签页(不要关闭原来的标签页),在新标签页中打开示例,可以看到控制台输出:

null
hello

可见,对于不同的标签页,SessionStorage 是无法共享数据的。一旦关闭了标签页或浏览器,存储的数据就再也找不回了。

应用

  • 比如文章编辑器的实时保存(以及断网时的保存策略)。
  • 一些不重要的用户设置。比如某些阅读类的网站,用户可以设置文章的字体大小、配色等。这些数据有时没必要保存在数据库。
  • 比如。。。你仔细想想,还是有很多的。

需要注意的是,不要太依赖于本地存储。本地存储虽然是永久的,但随时可能被用户或浏览器清理掉。此外,不同浏览器间也是无法共享数据的。

总结

无聊的补充

我们可以这样获取已经占用的存储空间大小:

var total = unescape(encodeURIComponent(JSON.stringify(localStorage))).length;
console.log(total / 1024 + 'K')

5M 左右的空间,也是会用满的:

for (let i = 0; i < 1024 * 1024; i++) {
    localStorage.setItem('test' + i, 'hello')
}

控制台输出:

Uncaught DOMException: Failed to execute 'setItem' on 'Storage': Setting the value of 'test356613' exceeded the quota.

意思是超出配额了。

我们也可以来测试你的浏览器对本地存储的最大允许容量。

for (let i = 0; i < 1024 * 1024; i++) {
    var total = unescape(encodeURIComponent(JSON.stringify(localStorage))).length;
    console.log(total / 1024 / 1024 + 'M')

    localStorage.setItem('test' + i, '0')
}

我试了两个浏览器,360浏览器崩溃了,谷歌浏览器显示 7M 多。

JavaScript 学习笔记 - LocalStorage的更多相关文章

  1. Java程序猿的JavaScript学习笔记(汇总文件夹)

    最终完结了,历时半个月. 内容包含: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源代码级解析. jQuery EasyUI源代码级解析. Java程序猿的J ...

  2. Java程序猿的JavaScript学习笔记(8——jQuery选择器)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  3. Java程序猿JavaScript学习笔记(2——复制和继承财产)

    计划和完成在这个例子中,音符的以下序列: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaSc ...

  4. Java程序猿的JavaScript学习笔记(3——this/call/apply)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  5. Java程序猿JavaScript学习笔记(4——关闭/getter/setter)

    计划和完成这个例子中,音符的顺序如下: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScr ...

  6. Java程序猿JavaScript学习笔记(14——扩大jQuery UI)

    计划和完成这个例子中,音符的顺序如下: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScr ...

  7. javascript学习笔记(四) Number 数字类型

    数字格式化方法toFixed().toExponential().toPrecision(),三个方法都四舍五入 toFixed() 方法指定小数位个数  toExponential() 方法 用科学 ...

  8. JavaScript学习笔记之数组(二)

    JavaScript学习笔记之数组(二) 1.['1','2','3'].map(parseInt) 输出什么,为什么? ['1','2','3'].map(parseInt)//[1,NaN,NaN ...

  9. JavaScript学习笔记[0]

    JavaScript学习笔记[0] 使用的是廖雪峰JavaScript教程. 数据类型 Number 表示数字,不区分浮点整形. === 比较时不转化数据类型. == 反之. NaN与任何值都不想等, ...

随机推荐

  1. Android 自定义 permission

    Android 自定义 permission Android 添加自定义权限 permission-tree 权限的根节点,3个成员都要定义 name 一般来说需要2个".":比如 ...

  2. tensorflow l2_loss函数

    1.l2_loss函数 tf.nn.l2_loss(t, name=None) 解释:这个函数的作用是利用 L2 范数来计算张量的误差值,但是没有开方并且只取 L2 范数的值的一半,具体如下: out ...

  3. html超级简单实现点赞(收藏)和取消赞效果

    1.前言 我们经常会遇到对一些列表呀进行点赞呀收藏数据等效果呀.今天就用html+css实现超级简单易上手的点赞和取消赞的demo展示. 2.详情 1.css样式 .like{ font-size:6 ...

  4. poj 3761 bubble sort (排列组合)

    #include<cstdio> #include<cstring> #define ll long long #define mod 20100713 ; ll a[maxn ...

  5. HDU 6043 KazaQ's Socks (规律)

    Description KazaQ wears socks everyday. At the beginning, he has nn pairs of socks numbered from 11  ...

  6. Word2016“此功能看似已中断 并需要修复”问题解决办法

    Word2016"此功能看似已中断 并需要修复"问题解决办法 修复步骤: 1. 按Windows 键+R键,输入"regedit"打开注册表. 2.找到以下键值 ...

  7. C#中调用HttpWebRequest类中Get/Post请求无故失效的诡异问题

    先附代码 /// <summary> /// 客户端Http(GET) /// </summary> /// <param name="strUrl" ...

  8. Handler实现线程之间的通信-下载文件动态更新进度条

    1. 原理 每一个线程对应一个消息队列MessageQueue,实现线程之间的通信,可通过Handler对象将数据装进Message中,再将消息加入消息队列,而后线程会依次处理消息队列中的消息. 2. ...

  9. 腾讯发布 Omix 1.0 - 用 JSX 或 hyperscript 创建用户界面

    腾讯发布 Omix 1.0 - 用 JSX 或 hyperscript 创建用户界面 今天,腾讯正式开源发布 Omix 1.0, 让开发者使用 JSX 或 hyperscript 创建用户界面. Gi ...

  10. Springboot+redis 整合

    运行环境: JDK1.7. SpringBoot1.4.7 redis3.0.4 1.生成Springboot项目,分别添加web,redis依赖,具体的maven依赖如下 <dependenc ...