引言
在日常开发中,我们经常遇到需要将 JavaScript 对象转化为 JSON 字符串进行传输或者持久化存储的情况,这时 JSON.stringify()
和 JSON.parse()
成为了我们的得力助手。然而,原生的 JSON 序列化并不能处理函数、日期、正则等非基础类型数据,这无疑给我们的工作带来了一定挑战。本文将探讨如何自定义序列化与反序列化方法以保留这些信息,并顺带提及在特定场景下,简单地使用解构赋值也能满足对象拷贝的需求。
函数类型的序列化与反序列化
原生 JSON 序列化会忽略对象中的函数成员。若要保留函数,我们可以创建自定义的序列化和反序列化函数。以下是一个简单的实现示例:
function customSerialize(obj) {
let copy = {...obj}; // 创建浅拷贝
if (typeof obj === 'function') {
copy._fnBody = obj.toString();
}
return copy;
}
function customDeserialize(jsonObj) {
if ('_fnBody' in jsonObj) {
jsonObj._fn = new Function(jsonObj._fnBody);
delete jsonObj._fnBody;
}
return jsonObj;
}
在这个例子中,我们将函数体转为字符串存储,并在反序列化时利用 new Function()
来重建函数。不过需要注意的是,动态创建函数存在一定的安全隐患,尤其在严格的安全策略环境中可能无法使用。
Date 和 RegExp 类型的序列化与反序列化
对于 Date 和 RegExp 类型,同样可以通过定制化的方法来进行序列化与反序列化:
function customSerialize(obj) {
let copy = {...obj};
if (obj instanceof Date) {
copy._date = obj.toISOString();
} else if (obj instanceof RegExp) {
copy._regex = [obj.source, obj.flags];
}
return copy;
}
function customDeserialize(jsonObj) {
if ('_date' in jsonObj) {
jsonObj._date = new Date(jsonObj._date);
} else if ('_regex' in jsonObj) {
jsonObj._regex = new RegExp(jsonObj._regex[0], jsonObj._regex[1]);
}
return jsonObj;
}
这里我们分别利用 toISOString()
方法将 Date 对象转为 ISO 格式字符串,将正则表达式的 source
和 flags
存储下来以便重构。
对象拷贝场景下的解构赋值
当我们的目标仅仅是复制对象而不涉及 JSON 序列化时,可以巧妙地使用 ES6 中的解构赋值语法实现深拷贝:
let originalObj = { a: 1, b: function() { console.log('hello'); }, c: new Date() };
let copiedObj = {...originalObj};
// 对于函数和 Date 类型,它们也会被正确复制
copiedObj.b(); // 输出 "hello"
console.log(copiedObj.c instanceof Date); // true
需要注意的是,解构赋值只能实现一层深度的浅拷贝,对于嵌套对象,需要递归或者其他深拷贝方法才能完整复制所有层级。
总结起来,虽然原生 JSON 序列化不支持函数、日期、正则等类型,但通过自定义序列化与反序列化方法,我们可以扩展这一能力。而在单纯的对象拷贝场景中,利用解构赋值不失为一种简洁高效的选择。在实际开发中,应根据具体需求选择最合适的方案。