JS深度克隆对象(克隆时包含函数)

在 JavaScript 中,标准的 JSON.stringify()JSON.parse() 无法直接处理函数,因为 JSON 格式不支持函数类型。若要实现对象与 JSON 字符串之间的相互转换,同时保留函数,可采用以下几种方法:

方法一:自定义序列化和反序列化函数

手动遍历对象,将函数转换为字符串存储,再恢复时重新解析为函数。

javascript 复制代码
function objectToJsonWithFunctions(obj) {
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === 'function') {
      return value.toString();
    }
    return value;
  });
}

function jsonToObjectWithFunctions(jsonStr) {
  return JSON.parse(jsonStr, (key, value) => {
    if (typeof value === 'string' && value.startsWith('function')) {
      // 使用 Function 构造函数重新创建函数
      return new Function(`return ${value}`)();
    }
    return value;
  });
}

// 使用示例
const original = {
  add: function(a, b) { return a + b; },
  greet: () => 'Hello',
  num: 42
};

const jsonStr = objectToJsonWithFunctions(original);
const restored = jsonToObjectWithFunctions(jsonStr);

console.log(restored.add(1, 2)); // 3
console.log(restored.greet());   // 'Hello'

方法二:使用第三方库 serialize-javascript

该库专门处理包含函数的对象序列化和反序列化。

bash 复制代码
npm install serialize-javascript
javascript 复制代码
const serialize = require('serialize-javascript');
const { deserialize } = require('serialize-javascript');

const original = {
  multiply: (a, b) => a * b,
  info: {
    name: 'Test',
    print: function() { console.log(this.name); }
  }
};

// 序列化(包含函数)
const serialized = serialize(original);

// 反序列化
const restored = deserialize(serialized);

console.log(restored.multiply(3, 4)); // 12
restored.info.print(); // 'Test'

方法三:使用 eval()(不推荐,有安全风险)

直接使用 eval() 解析函数字符串,存在代码注入风险,仅适用于受信任环境。

javascript 复制代码
function jsonToObjectWithEval(jsonStr) {
  return JSON.parse(jsonStr, (key, value) => {
    if (typeof value === 'string' && value.match(/^function|^\([^)]*\)\s*=>/)) {
      return eval(`(${value})`); // 注意:存在安全风险
    }
    return value;
  });
}

注意事项

  1. 函数上下文丢失 :反序列化后的函数可能丢失原有的 this 上下文。
  2. 闭包信息丢失:函数内部引用的外部变量无法恢复。
  3. 安全风险 :使用 eval()new Function() 可能执行恶意代码,仅用于受信任数据。
  4. 复杂场景:对于包含正则表达式、日期等特殊对象的函数,可能需要额外处理。

最佳实践

优先使用 方法二serialize-javascript),它能更安全地处理函数序列化,避免常见陷阱:

javascript 复制代码
const serialized = serialize(original, {
  ignoreFunction: false, // 不忽略函数
});

const restored = deserialize(serialized);

通过上述方法,可在 JSON 转换过程中保留函数定义,但需注意函数上下文和安全性问题。

相关推荐
励志不掉头发的内向程序员1 小时前
STL库——string(类函数学习)
开发语言·c++
刺客-Andy1 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js
一百天成为python专家1 小时前
Python循环语句 从入门到精通
开发语言·人工智能·python·opencv·支持向量机·计算机视觉
Sunhen_Qiletian1 小时前
朝花夕拾(五)--------Python 中函数、库及接口的详解
开发语言·python
hqwest1 小时前
C#WPF实战出真汁07--【系统设置】--菜品类型设置
开发语言·c#·wpf·grid设计·stackpanel布局
前路不黑暗@2 小时前
C语言:操作符详解(二)
c语言·开发语言·经验分享·笔记·学习·学习方法·visual studio
深盾科技3 小时前
Kotlin Data Classes 快速上手
android·开发语言·kotlin
zzywxc7873 小时前
详细探讨AI在金融、医疗、教育和制造业四大领域的具体落地案例,并通过代码、流程图、Prompt示例和图表等方式展示这些应用的实际效果。
开发语言·javascript·人工智能·深度学习·金融·prompt·流程图
大明883 小时前
用 mouseover/mouseout 事件代理模拟 mouseenter/mouseleave
前端·javascript
林太白3 小时前
Nuxt.js搭建一个官网如何简单
前端·javascript·后端