关于 localStorage 使用的一些问题

我们知道,localStorage 只接受字符串类型的键值,因此当我们需要存储引用类型时,需要先进行序列化。

先来看一下不进行序列化会有什么问题:

let obj = {
    name: "dby",
    age: 12,
    sex: 0
}
localStorage.setItem("user", obj);

打开 Chrome 开发者工具,选择 Application ,然后点 localStorage ,可以看到刚才存进去的 user 字段,该字段的值变成了 [object Object] 。这说明 localStorage 在存储的时候,对于非字符串的值,会尝试调用 toString 方法转为字符串,但是 Object 类型调用 toString 只会输出对象的内部属性 [object Object]
在这里插入图片描述
同理,对于 Array 类型,直接存进去也会调用 toString 方法:

localStorage.setItem("user", [1, 2, 3, 4]);

在这里插入图片描述
因此,当需要用 localStorage 存储引用类型的值,需要用 JSON.stringify 方法进行序列化。

let obj = {
	name: "dby",
    age: 12,
    sex: 0
}
localStorage.setItem("user", JSON.stringify(user));

在实际开发中,通常会对这个操作进行封装,下面介绍一下常用的处理方法。

本地存储方法封装

这边封装了两个方法 storageSetstorageGet

function storageSet(key, value) {
	if (value instanceof Object) {
        // 引用类型,包括 Object 和 Array
        localStorage.setItem(key, JSON.stringify(value));
    } else {
    	// 基本类型直接存储
    	// 注意如果不是 string 类型,则会调用 toString 方法尝试转为 string
        localStorage.setItem(key, value);
    }
}
function storageGet(key) {
	let str = localStorage.getItem(key);
    try {
    	// 如果值不是 JSON 对象,会导致反序列化失败,因此这边用 try catch 包裹一下
        return JSON.parse(str);
    } catch (error) {
    	// 不是 JSON 对象,直接返回字符串
        return str;
    }
}

这边有两个注意点:

1. 判断引用类型,这边用了 instanceof ,当然也可以使用 typeof value == "object" 进行判断,只不过 null 也会被判断为 true

2. 如果值不是 JSON 对象,调用 JSON.parse 会导致反序列化失败,因此这边用了 try catch 包裹一下;

3. 在 JSON 序列化的时候,会忽略 undefined 、symbol 值和函数,因此对象中最好不要包含这些类型;

重写对象的 toString 方法

在面向对象编程中有一大特征叫做多态,既然对象的 toString 方法会返回 [object Object] ,那么如果我们重写对象的 toString 方法,就可以避免输出对象的内部属性了。

重写有几种方式,但是像下面这样直接覆盖是不推荐的,会导致原型链污染:

Object.prototype.toString = function() {
	...
}

有一种简单的方法,直接在对象里面添加 toString 方法:

let obj = {
	name: "dby",
    age: 12,
    sex: 0,
    toString() {
		return JSON.stringify(this);
	}
}
obj.toString();
// "{\"name\":\"dby\",\"age\":12,\"sex\":0}"

刚才说了 JSON 序列化的时候会忽略函数,因此我们添加的 toString 方法并不会出现在结果里面。

还有一种就是我们创建一个类,然后用这个类去继承 Object 类,在这个类中重写 toString 方法:

class MyObject extends Object {
	@Override
	toString() {
        return JSON.stringify(this);
    }
}

注意这个时候我们创建对象不能再用字面量 {} ,必须得像下面这样:

let obj = new MyObject();
obj.name = "dby";
obj.age = 12;
obj.sex = 0;
obj.toString();
// "{\"name\":\"dby\",\"age\":12,\"sex\":0}"
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值