JSON.parse,JSON.stringify 深浅拷贝的缺陷(欢迎评论)

3,306 阅读1分钟

JSON.parse,JSON.stringify 深浅拷贝的缺陷

经常使用 JSON.parse, JSON.stringify 的小伙伴都知道,他们两个可以用于深拷贝对象,但是可能会不太注意一些缺陷,是又一次我使用他们去深拷贝对象,我发现有些属性莫名其妙的丢失了,之前没有太深究其弊端,今天趁着有空深究一下这些弊端。

首先我们来看下代码:

let deepClone = function(obj) {
    return JSON.parse(JSON.stringify(obj))
}
let a = {
    name: 'Ken',
    age: 18,
    hobbit: ['dance', 'sing', {type: 'sports', value: 'run'}],
    schoolData: {
        grades: 'A',
    },
    run: function() {},
    walk: undefined,
    fly: NaN,
    cy: null
}

let b = deepClone(a)
console.log("b", b)

/**

{
    age: 18,
    cy: null,
    fly: null,
    hobbit: (3) ["dance", "sing", {…}],
    name: "Ken",
    schoolData: {grades: "A"},
}

 * */ 

对比原有的对象,我们可以知道:

  1. 不会拷贝对象上的 value 值为 undefined 和 函数的键值对
  2. NaN,无穷大,无穷小会被转为 null

自定义对象测试

let Ken = function() {
    this.name = "Ken"
}

Ken.prototype.walk = function() {
    console.log("walk")
}

let KenNaNa = function() {
    Ken.call(this, arguments)
    this.name = "KenNaNa"
}

let tempFunc = function() {}
tempFunc.prototype = Ken.prototype
KenNaNa.prototype = new tempFunc()
KenNaNa.prototype.age = "18"
KenNaNa.prototype.run = function() {
    console.log("run")
}

Object.defineProperty(KenNaNa.prototype, "contructor", {
    value: KenNaNa,
    enumerable:false
})

let kenNaNa = new KenNaNa()
let copyKenNaNa = JSON.parse(JSON.stringify(kenNaNa))

/**
 Ken {age: "18", run: ƒ, contructor: ƒ}
 * */ 
console.log(copyKenNaNa.constructor); // ƒ Object() { [native code]}
console.log(copyKenNaNa.age) // undefined
console.log(copyKenNaNa.run()) // is not function
console.log(copyKenNaNa.walk()) // is not function 
console.log(copyKenNaNa.toString()) // "[object Object]"
  1. 无法获取原型上面的方法,属性,只能获取 Object 原型的内容
var date = new Date()
var copy = JSON.parse(JSON.stringify(date))

console.log("copy", copy) // "2021-01-14T06:47:12.337Z"

总结

  1. 取不到值为 undefined 的 key
  2. NaN 和 无穷大,无穷小转变为 null
  3. 取不到原型的内容
  4. date 对象转变为 date 字符串

补充评论

循环引用会报错

Symbol() 会丢失