SOURCE

/*
 深拷贝:一、JSON.parse(JSON.stringify(obj))
            JSON.stringify:对象序列化;JSON.parse:反序列化js对象
            问题:1.obj存在时间对象的话,JSON.parse(JSON.stringify(obj))后会变成字符串,就无法使用new Date的其他方法如getFullYear()
                 2.存在RegExp、Error对象,序列化后变成空对象
                 3.存在函数、undefined,序列化后会丢失
                 4.存在NaN、Infinity,序列化后会变成null
                 5.JSON.stringfy()只能序列化对象的可枚举的自有属性,如obj的对象是由构造函数生成的,则JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor
        二、deepClone
        三、lodash:_.cloneDeep(obj)
*/

/*
    浅拷贝:Object.assign()、扩展运算符、concat、slice、

 */

// 深拷贝
function deepClone(source) {
    const targetObj = source.constructor === Array ? [] : {}
    for (let keys in source) {
        if (source.hasOwnProperty(keys)) {
            if (source[keys] && typeof source[keys] === 'object') {
                // 引用数据类型
                targetObj[keys] = deepClone(source[keys])
            } else {
                // 基本数据类型
                targetObj[keys] = source[keys]
            }
        }
    }
    return targetObj
}

const obj = {
    name: 'obj',
    js: {
        name: '深拷贝',
    },
    age: [1, 2, 3]
}
const copyObj = deepClone(obj)
copyObj.name = '深拷贝2'
console.log(obj, copyObj)

// 问题1:存在时间对象的话,JSON.parse(JSON.stringify(obj))后会变成字符串
const obj1 = {
    date: new Date(),
}
const copyObj1 = JSON.parse(JSON.stringify(obj1))
// console.log(copyObj1.date.getFullYear()) // =>报错

// 问题2:存在RegExp、Error对象,序列化后变成空对象
const obj2 = {
    name: 'test',
    reg: new RegExp('\\w+'),
    error: new Error(123)
}
const copyObj2 = JSON.parse(JSON.stringify(obj2))
// console.log(copyObj2)
function eavl() {
    try {
        throw copyObj2.error
    } catch (e) {
        // console.log("问题2:", e.message) // =>清空后打印为undefined
    }
}
eavl()

// 问题3:存在函数、undefined,序列化后会丢失
const obj3 = {
    name: undefined,
    getInfo: function getPersonInfo() {
        console.log('123')
    },
    age: 10
}
const copyObj3 = JSON.parse(JSON.stringify(obj3))
// console.log(obj3, copyObj3)

// 问题4:存在NaN、Infinity,序列化后会变成null
const obj4 = {
    name: Number('a'),
    infinity: 1 / 0,
    age: 12
}
const copyObj4 = JSON.parse(JSON.stringify(obj4))
// console.log(obj4, copyObj4)

// 问题5:JSON.stringfy()只能序列化对象的可枚举的自有属性,如obj的对象是由构造函数生成的,则JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor
function Person(name) {
    this.name = name
}
const jsrun = new Person('jsrun')
const obj5 = {
    name: 'obj5',
    jsrun: jsrun
}
const copyObj5 = JSON.parse(JSON.stringify(obj5))
// console.log(obj5, copyObj5)
console 命令行工具 X clear

                    
>
console