Js拷贝之深浅拷贝

起深浅拷贝那必须说到数据类型(基本数据类型、引用数据类型)

基本数据类型:赋值,赋值之后两个变量互不影响,存在栈中

引用数据类型:赋址,两个变量的引用相同,指向同一个对象,数据存在堆,引用地址存在栈中

一、 浅拷贝

浅拷贝只解决了第一层的问题,拷贝第一层的基本类型值,以及第一层的引用类型地址

浅拷贝方法: Object.assign()对象合并、...展开运算符、普通遍历拷贝

方法一:Object.assign()

let a = {
    name: 'liben',
    age: 22,
    sex: null,
    partner: undefined,
    like: ['czb', 'lol', 'money'],
    school: {
        addr: '湖南',
        email: '123'
    }
}
let copy_1 = Object.assign({}, a)
// console.log(copy_1)

方法二:...展开运算符

let copy_2 = {...a};
// console.log("copy_2>>>", copy_2)

方发三:普通遍历

function deepCopy (obj) {
    let _obj = Array.isArray(obj) ? [] : {};
    for(let key in obj) {
        _obj[key] = obj[key]
    }
    return _obj;
}
let copy_3 = deepCopy(a);
// console.log(copy_3)

二、深拷贝

深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。

深拷贝方法:JSON.parse(JSON.stringify(obj))、普通递归

方法一:JSON.parse(JSON.stringify(obj))

let a = {
    name: 'liben',
    age: 22,
    sex: null,
    partner: undefined,
    like: ['czb', 'lol', 'money'],
    school: {
        addr: '湖南',
        email: '123'
    }
}
let copyA1 = JSON.parse(JSON.stringify(a))
a.school.addr = '深圳'
console.log(a, copyA1)

缺点:

  • 会忽略属性值undefined和symbol

  • 值为正则会转为{}

  • 无法深拷贝循环引用

方法二:普通递归

function deep_copy (obj) {
    let _obj = Array.isArray(obj) ? [] : {};  // 判断数组或者对象引用

    for(let key in obj) {
        console.log(key, Object.prototype.toString.call(obj[key]))
        if (typeof obj[key] === 'object' && obj[key] !== null) { // 处理null为object类型
            _obj[key] = deep_copy(obj[key])
        } else {
            _obj[key] = obj[key]
        }
    }
    return _obj;
}

let copyA3 = deep_copy(a);
a.like[0] = 'csb'
console.log("copyA3>>>", a, copyA3)

这里只是对拷贝原理的简单实现,拷贝还有其它一些框架实现了,比如jq.extend,lodash库等

你可能感兴趣的:(Js拷贝之深浅拷贝)