你还在用JSON.parse(JSON. stringify('xxx'))进行深拷贝吗?

308 阅读2分钟

面试官提问?你觉得JSON.parse(JSON. stringify('xxx'))进行深拷贝和用库深拷贝区别有哪些?

因为项目都这么用

哈哈哈哈当然不是啦!

那么使用JSON.parse(JSON. stringify('xxx'))进行深拷贝到底有哪些缺点呢?

1. 无法克隆函数和方法

  • 限制:JSON 不支持函数,所以在序列化过程中,任何对象的方法或函数属性都会丢失。

  • 示例

    javascript
    复制代码
    const original = {
      name: 'John',
      greet: function() { console.log('Hello!'); }
    };
    const clone = JSON.parse(JSON.stringify(original));
    console.log(clone.greet); // undefined
    

2. 无法克隆特殊对象类型

  • 限制:JSON 仅支持基本的 JavaScript 数据类型(如字符串、数字、布尔值、数组和普通对象)。对于特殊的对象类型,如 DateSetMapRegExp 等,克隆结果会丢失其原有类型和行为。

  • 示例

    javascript
    复制代码
    const original = {
      date: new Date(),
      regExp: /test/g
    };
    const clone = JSON.parse(JSON.stringify(original));
    console.log(clone.date instanceof Date); // false
    console.log(clone.regExp instanceof RegExp); // false
    

3. 无法处理循环引用

  • 限制:如果对象包含循环引用,JSON.stringify 会抛出错误,因为 JSON 无法表示这种结构。

  • 示例

    javascript
    复制代码
    const original = {};
    original.self = original;
    // JSON.stringify(original); // Uncaught TypeError: Converting circular structure to JSON
    

4. 性能问题

  • 限制:对于大型对象,JSON.stringifyJSON.parse 可能会带来性能问题,因为它们会进行完整的序列化和反序列化过程。
  • 示例:在大型数据集上进行多次克隆操作时,可能会导致性能瓶颈。

5. 精度问题

  • 限制:对于超出 JavaScript 数值精度范围的数值(如非常大的整数),在序列化和反序列化过程中可能会丢失精度。

  • 示例

    javascript
    复制代码
    const original = { number: 12345678901234567890 };
    const clone = JSON.parse(JSON.stringify(original));
    console.log(clone.number); // 12345678901234568000
    

替代方法

对于需要克隆特殊类型或处理循环引用的情况,可以考虑使用更强大的深克隆库,如 lodashcloneDeep 方法:

javascript
复制代码
import _ from 'lodash';

const original = {
  name: 'John',
  date: new Date(),
  nested: {
    number: 123,
  },
};

const clone = _.cloneDeep(original);
console.log(clone);

lodashcloneDeep 方法能够正确处理函数、特殊对象类型和循环引用,且在性能上比 JSON.parse(JSON.stringify()) 更为优化。