localStorage

作用

  1. 一种持久化方式数据的存储,HTML5新增的内容
  2. IE8+和标准浏览器支持,移动端可以放心使用
  3. cookie存储量小,4k,localStorage可以高达10M左右
  4. 在相同的域名和端口号下页面,可以共享localStorage中的数据.
  5. 存入localStorage中的数据,除非你主动删除,否则一直都在.

💡 注意:都是以字符串的形式来存储数据的.

用处

  1. 登录完成后token的存储
  2. 用户部分信息的存储,比如昵称、头像、简介
  3. 一些项目通用参数的存储,例如某个id、某个参数params
  4. 项目状态管理的持久化,例如vuex的持久化、redux的持久化
  5. 项目整体的切换状态存储,例如主题颜色、icon风格、语言标识

缺陷

  • 1、命名过于简单

    • 1、比如我们存用户信息会使用user作为 key 来存储
    • 2、存储主题的时候用theme 作为 key 来存储
    • 3、存储令牌时使用token作为 key 来存储

     💡 同源的两个项目,它们的localStorage是互通的。

    举个例子比如 现在有两个项目,在同源 URL下,两个项目都需要往localStorage中存储一个 key 为name的值,那么这就会造成两个项目的name互相顶替的现象,也就是互相污染现象

  • 2、时效性

    • localStorage:除非手动清除,否则一直存在
    • sessionStorage:生命结束于当前标签页的关闭或浏览器的关闭

    💡 其实普通的使用时没什么问题的,但是给某些指定缓存加上特定的时效性,是非常重要的!

  • 3、隐秘性

    • 点击Application就可以看到,localStorage的内容

    💡 做状态管理持久化时,需要把数据先存在localStorage中,这个时候就很有必要对缓存进行加密了

解决方案

  • 命名规范
    • 项目名 + 当前环境 + 项目版本 + 缓存key (根据需求自己调整)
  • expire定时
    • 设置缓存key时,将value包装成一个对象,对象中有相应的时效时段
    • 当下一次想获取缓存值时,判断有无超时,不超时就获取value,超时就删除这个缓存
  • crypto加密
    • 加密很简单,直接使用crypto-js进行对数据的加密,使用这个库里的encrypt、decrypyt进行加密、解密

方法

  • add/edit

    // 基础变量
    
    	// 方式一 .
    	localStorage.cb = "城邦";
    	// 方式二 []
    	localStorage["xk"] = "小可";
    	// 方式三 setItem("属性名/变量","值/变量");
    	var stu = "赵莉";
    	var age = 18;
    	localStorage.setItem(stu,age);
    	console.log((localStorage["赵莉"]));
    
    // 引用变量
    
    	var stuStr = JSON.stringify(stu);
    	localStorage.stu = stuStr;
    
  • get

    // 基础变量	
    
    	// 方式一 .
    	localStorage.cb;
    	// 方式二 []
    	localStorage["赵莉"];
    	// 方式三 getItem("属性名"/变量名)
    	localStorage.getItem("a”);   
    
    // 引用变量
    
    	var stuStr = localStorage.stu;
    	var oStu = JSON.parse(stuStr);
    
  • delet

    // 方式一 delete
    delete localStorage.cb;
    // 方式二 removeItem("属性名"/变量名)
    localStorage.removeItem("赵莉");
    
    // 清空
    localStorage.clear();
    
  • length

    // 只读属性,赋值没有效果
    localStorage.length = 1;
    
  • 遍历

    for (var key in localStorage) {
    	console.log(key,localStorage[key],localStorage.getItem(key));
    };
    

localStorage 存储的键值采用什么字符编码?

  • localStorage 存储的键和值始终采用 UTF-16 DOMString 格式,每个字符使用两个字节。与对象一样,整数键将自动转换为字符串。

5M?

  • 字符的长度 或 utf-16编码单元 或 10M字节空间
// 字符的个数,并不等于字符的长度

"a".length // 1
"人".length // 1
"𠮷".length // 2
"🔴".length // 2
  • 而根据 UTF-16编码规则,要么2个字节,要么四个字节,所以不如说是 10M 的字节数,更为合理。
  • 当然,2个字节作为一个utf-16的字符编码单元,也可以说是 5M 的utf-16的编码单元。
  • utf-16字符串计算字节数的方法:判断码点决定是2还是4
function sizeofUtf16Bytes(str) {
    var total = 0,
        charCode,
        i,
        len;
    for (i = 0, len = str.length; i < len; i++) {
        charCode = str.charCodeAt(i);
        if (charCode <= 0xffff) {
            total += 2;
        } else {
            total += 4;
        }
    }
    return total;
}

// 留下8个字节数作为key,8个字节可是普通的4个字符换,也可是码点大于65535的3个字符,也可是是组合
// aaaa
// aa🔴
// 🔴🔴

const charTxt = "人";
let count = (10 * 1024 * 1024 / 2) - 8 / 2;
let content = new Array(count).fill(charTxt).join("");
const key = "aa🔴";
localStorage.clear();
try {
    localStorage.setItem(key, content);
} catch (err) {
    console.log("err", err);
}

const sizeKey = sizeofUtf16Bytes(key);
const contentSize = sizeofUtf16Bytes(content);
console.log("key size:", sizeKey, content.length); // key size: 8 5242876
console.log("content size:", contentSize, content.length); // content size: 10485752 5242876
console.log("total size:", sizeKey + contentSize, content.length + key.length); // total size: 10485760(10M) 5242880 

localStorage 键占不占存储空间?

  • 占空间
// key和val各自设置长 2.5M的长度

const charTxt = "a";
let count = (2.5 * 1024 * 1024);
let content = new Array(count).fill(charTxt).join("");
const key = new Array(count).fill(charTxt).join("");
localStorage.clear();
try {
    console.time("setItem")
    localStorage.setItem(key, content);
    console.timeEnd("setItem")
} catch (err) {
    console.log("err code:", err.code);
    console.log("err message:", err.message)
}
// 把content的长度加1, 变为 2.5 M + 1, key的长度依旧是 2.5M的长度
// 超出存储空间

const charTxt = "a";
let count = (2.5 * 1024 * 1024);
let content = new Array(count).fill(charTxt).join("") + 1;
const key = new Array(count).fill(charTxt).join("");
localStorage.clear();
try {
    console.time("setItem")
    localStorage.setItem(key, content);
    console.timeEnd("setItem")
} catch (err) {
    console.log("err code:", err.code);
    console.log("err message:", err.message)
}

键的数量,对读写的影响

  • 键的数量对读取性能有影响,但是不大。
  • 值的大小对性能影响更大,不建议保存大的数据。
// 500 * 1000键

let keyCount = 500 * 1000;

localStorage.clear();
for (let i = 0; i < keyCount; i++) {
    localStorage.setItem(i, "");
}

setTimeout(() => {
    console.time("save_cost");
    localStorage.setItem("a", "1");
    console.timeEnd("save_cost");
}, 2000)

setTimeout(() => {
    console.time("read_cost");
    localStorage.getItem("a");
    console.timeEnd("read_cost");

}, 2000)

// save_cost: 0.05615234375 ms
// read_cost: 0.008056640625 ms

// 单独执行
localStorage.clear();    
console.time("save_cost");
localStorage.setItem("a", "1");
console.timeEnd("save_cost");
// save_cost: 0.033203125 ms
  • 保存的值表较大
const charTxt = "a";
const count = 5 * 1024 * 1024  - 1
const val1 = new Array(count).fill(charTxt).join("");

setTimeout(() =>{
    localStorage.clear();
    console.time("save_cost_1");
    localStorage.setItem("a", val1);
    console.timeEnd("save_cost_1");
},1000)

setTimeout(() =>{
    localStorage.clear();
    console.time("save_cost_2");
    localStorage.setItem("a", "a");
    console.timeEnd("save_cost_2");
},1000)

// save_cost_1: 12.276123046875 ms
// save_cost_2: 0.010009765625 ms
  • 单次值的大小对存的性能影响非常大,读取也一样
  • 尽量不要保存大的值,因为其是同步读取,纯大数据,用indexedDB

localStorage 功能检测

function storageAvailable(type) {
    var storage;
    try {
        storage = window[type];
        var x = '__storage_test__';
        storage.setItem(x, x);
        storage.removeItem(x);
        return true;
    }
    catch(e) {
        return e instanceof DOMException && (
            // everything except Firefox
            e.code === 22 ||
            // Firefox
            e.code === 1014 ||
            // test name field too, because code might not be present
            // everything except Firefox
            e.name === 'QuotaExceededError' ||
            // Firefox
            e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
            // acknowledge QuotaExceededError only if there's something already stored
            (storage && storage.length !== 0);
    }
}

if (storageAvailable('localStorage')) {
  // Yippee! We can use localStorage awesomeness
}
else {
  // Too bad, no localStorage for us
}

localStorage已使用空间统计

function sieOfLS() {
    return Object.entries(localStorage).map(v => v.join('')).join('').length;
}

localStorage.clear();
localStorage.setItem("🔴", 1);
localStorage.setItem("🔴🔴🔴🔴🔴🔴🔴🔴", 1111);
console.log("size:", sieOfLS())   // 23
// 🔴*9 + 1 *5 = 2*9 + 1*5 = 23

Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.icon-default.png?t=LBL2https://serious-lose.notion.site/localStorage-78d018365e6b442ba6dc77874f7823ee

使用 Web Storage API - Web API 接口参考 | MDN

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值