本文介绍一种实现json深拷贝的方法,尤其针对包含函数的情况。该方法包含两个核心函数:tojson 和 parsejson,分别用于将对象序列化为json字符串并还原json字符串为对象,同时完整保留函数信息。

tojson 函数:序列化对象为JSON字符串
该函数利用JSON.stringify方法将对象转换为JSON字符串。关键在于其第二个参数,一个自定义函数,用于处理函数类型的属性。该函数会识别并用特殊前缀和后缀包裹函数代码,从而在序列化过程中保存函数信息。 ES5和ES6箭头函数均被支持。
import deepextend from './deepextend';
const prefix = '[[form-create-prefix-';
const suffix = '-form-create-suffix]]';
const $t = '$fn:';
const functionKeyword = 'function'; // 使用更清晰的变量名
export function tojson(obj, space) {
return JSON.stringify(deepextend([], obj, true), function (key, val) {
if (typeof val !== functionKeyword) {
return val;
}
if (val.__json) {
return val.__json;
}
if (val.__origin)
val = val.__origin;
if (val.__emit)
return undefined;
return prefix + val + suffix;
}, space);
}
parsejson 函数:将JSON字符串还原为对象
该函数使用JSON.parse方法将JSON字符串解析回对象。同样,其第二个参数是一个自定义函数,用于处理被特殊标记的函数字符串。它会识别并使用makefn函数将函数字符串还原为可执行的函数对象。
import is, {hasproperty} from './type';
function makefn(fnString) {
return (new Function('return ' + fnString))(); // 使用Function构造函数更清晰
}
export function parsefn(fn, mode) {
if (fn && is.string(fn) && fn.length > 4) {
let v = fn.trim();
if (v.indexOf(suffix) > 0 && v.indexOf(prefix) === 0) {
v = v.replace(suffix, '').replace(prefix, '');
return makefn(v);
} else if (v.indexOf($t) === 0) {
v = v.replace($t, '');
return makefn(v);
} else if (!mode && v.indexOf(functionKeyword) === 0 && v !== functionKeyword) {
return makefn(v);
}
}
return fn;
}
export function parsejson(jsonString, mode) {
return JSON.parse(jsonString, function (k, v) {
if (is.undef(v) || !v.indexOf) return v; // 使用更清晰的条件判断
return parsefn(v, mode);
});
}
使用方法示例:
const data = {
rule: [
{
type: "input",
field: "goods_name",
title: "商品名称",
on: {
change: function (val) {
console.log("aa", val);
},
input: (val) => {
console.log("bb", val);
},
},
},
],
};
const jsonStr = tojson(data);
const dataCopy = parsejson(jsonStr);
通过以上步骤,即可实现包含函数的JSON对象的深拷贝。 代码中已对变量名和代码逻辑进行了一些优化,使其更易于理解和维护。 请确保deepextend和type模块已正确引入。










