JavaScript之深拷贝与浅拷贝

作者: 慕时_木雨凡 | 来源:发表于2019-10-30 11:47 被阅读0次

深拷贝和浅拷贝

  1. 深拷贝:改变拷贝后的结果,不会影响拷贝之前的内容
  2. 浅拷贝:改变拷贝后的结果,会影响拷贝之前的内容

最常用的 es6 ...扩展运算符 实现拷贝

// 单层对象 -- 深拷贝
let obj = {name: 'mushi', age: 28}
let copy = {...obj}
obj.age = 29
console.log(obj, copy) // { name: 'mushi', age: 29 } { name: 'mushi', age: '28' }

// 对象嵌套 -- 浅拷贝
let obj1 = {name: 'mushi', age: 28, job: [1,2]}
let copy1 = {...obj1}
obj1.job.push(3)
console.log(obj1, copy1) // { name: 'mushi', age: 28, job: [ 1, 2, 3 ] } { name: 'mushi', age: 28, job: [ 1, 2, 3 ] }

Object.assign() 实现拷贝

// 单层对象 -- 深拷贝
let obj = {name: 'mushi', age: 28}
let copy = Object.assign({}, obj)
obj.age = 29
console.log(obj, copy) // { name: 'mushi', age: 29 } { name: 'mushi', age: '28' }

// 对象嵌套 -- 浅拷贝
let obj1 = {name: 'mushi', age: 28, job: [1, 2]}
let copy1 = Object.assign({}, obj1)
obj1.job.push(3)
console.log(obj1, copy1) // { name: 'mushi', age: 28, job: [ 1, 2, 3 ] } { name: 'mushi', age: 28, job: [ 1, 2, 3 ] }

Array.slice() 和 Array.concat()

// 单层数组 -- 深拷贝
let a = [1,2,3]
let b = a.slice(); // let b = a.concat([])
a.push(4)
console.log(a, b) // [ 1, 2, 3, 4 ] [ 1, 2, 3 ]


// 嵌套数组 -- 浅拷贝
let c = [1,2,3, ['a', 'b']]
let d = c.slice(); // let d = c.concat([])
c[3].push('c')
console.log(c, d) // [ 1, 2, 3, [ 'a', 'b', 'c' ] ] [ 1, 2, 3, [ 'a', 'b', 'c' ] ]

JSON.parse 和 JSON.stringify实现深拷贝

  1. 效率比较低
  2. 不能实现复杂的深拷贝Map, Set, RegExp, Date, ArrayBuffer 和其他内置类型在进行序列化时会丢失
let obj = {a: 1, b: 2, c: {d: 3}}
let copy = JSON.parse(JSON.stringify(obj))
obj.c.d = 300
console.log(obj, copy) // { a: 1, b: 2, c: { d: 300 } } { a: 1, b: 2, c: { d: 3 } }

对象中包含一些内置对象或者函数对象

// 拷贝函数对象会丢失
let obj = {a: 1, b: () => {}}
let copy = JSON.parse(JSON.stringify(obj))
obj.a = 2
console.log(obj, copy) // { a: 2, b: [Function: b] } { a: 1 }

// 拷贝内置对象会丢失
let obj1 = {a: 1, b: new RegExp()}
let copy1 = JSON.parse(JSON.stringify(obj1))
obj1.a = 2
console.log(obj1, copy1) // { a: 2, b: /(?:)/ } { a: 1, b: {}}

自己封装deepCopy函数进行深拷贝

  1. 利用for in 循环进行拷贝
  2. 排除一些其他异常数据
  3. 使用new WeakMap()对拷贝过的数据进行存储防止重复循环引用
  4. 递归循环
function deepCopy (obj, hash = new WeakMap()) {
    if (obj === null || obj === undefined) return obj;
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj);
    if (typeof obj !== 'object') return obj; // 函数是不需要深拷贝的
    if (hash.get(obj)) return hash.get(obj); // 如果obj被拷贝过就直接返回
    let cloneObj = new obj.constructor; // 申明一个cloneObj类型obj保持一致
    hash.set(obj, cloneObj) // 将当前对象和拷贝对象存入hash中
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            cloneObj[key] = deepCopy(obj[key], hash)
        }
    }
    return cloneObj
}
let obj = {a: 1, b: {c: 2, d: 3}}
let copy = deepCopy(obj);
obj.a = 100
console.log(obj, copy) // { a: 100, b: { c: 2, d: 3 } } { a: 1, b: { c: 2, d: 3 } }

相关文章

  • 深入理解JavaScript中的堆与栈 、浅拷贝与深拷贝

    JavaScript中的浅拷贝与深拷贝 学了这么长时间的JavaScript想必大家对浅拷贝和深拷贝还不太熟悉吧,...

  • 浅拷贝和深拷贝

    本文参考:JavaScript中的浅拷贝和深拷贝js 深拷贝 vs 浅拷贝深入剖析 JavaScript 的深复制...

  • Objective-C中的浅拷贝和深拷贝

    Objective-C中的浅拷贝和深拷贝IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解iOS ...

  • js浅拷贝和深拷贝

    javaScript的变量类型 javaScript的变量类型基本类型:引用类型: 浅拷贝和深拷贝的区分 浅拷贝浅...

  • 初探浅拷贝&深拷贝

    思考 这个代码为什么具有深拷贝作用 浅拷贝与深拷贝 在JavaScript中,对于Object和Array这类引用...

  • JavaScript之深拷贝与浅拷贝

    深拷贝和浅拷贝 深拷贝:改变拷贝后的结果,不会影响拷贝之前的内容 浅拷贝:改变拷贝后的结果,会影响拷贝之前的内容 ...

  • JavaScript深拷贝、浅拷贝

    JavaScript深拷贝、浅拷贝 浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也...

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

  • JavaScript浅拷贝与深拷贝

    定义 浅拷贝(shallow copy):只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存。深拷贝...

  • 浅拷贝与深拷贝(JavaScript)

    一、预备知识 ECMAScript变量包含两种不同数据类型的值:基本数据类型和引用数据类型。基本数据类型:名值存储...

网友评论

    本文标题:JavaScript之深拷贝与浅拷贝

    本文链接:https://www.haomeiwen.com/subject/whdovctx.html