Js实现深浅复制

更新日期: 2019-11-02阅读: 1.7k标签: 拷贝

为什么有深复制、浅复制?

JavaScript中有两种数据类型,基本数据类型如undefined、null、boolean、number、string,另一类是Object。简单数据类型只存储在内存中的栈区,复制的时候是值传递给新的索引。而复杂数据类型由栈区和堆区共同储存,栈区执行同样的操作,只是把堆地址复制了一份,而真实数据在堆区中依然只有一份。
为了不影响原有数据,那么我们就新建一个对象,遍历原有对象的属性赋值到新属性。

let newObj = {}
for (let prop in obj) {
  newObj[prop] = obj[prop]
}

上面这个循环也可以用Object.assign({}, obj);来实现。
这样做是否解决问题?未必,因为Object中可以嵌套Object,如果原有对象属性中有复杂数据类型,那么新的对象中也只能得到一个地址。这种情况被称为浅复制。我们希望能将对象中的对象,无论多少层,都能复制一份,能达到这种效果的,称为深复制


深复制的几种方法

首先假设有数据

let obj = {
    a: 23,
    b: [0, 1, [2, 3], function() {console.log('in array')}, undefined],
    c: {k: 'value'},
    d: function() {console.log('a')}
    }

JSON.parse(JSON.stringify(obj))

let newObj = JSON.parse(JSON.stringify(obj))
newObj.newKey = 'newValue'
console.log(obj)
console.log(newObj)

如果处理对象只是简单的键值对,这个方法效果不错。

这个方法的缺点

  • 无法复制函数
  • 忽略undefined值
  • 无法处理Set、Map、Symbol类型(即使用上repalce参数)
  • 原有的原型链会消失
  • 循环引用的对象会报错

递归法

因为要处理属性的值也是Object这种情况,自然可以想到递归这种处理方法。

function deepCopy(oldObj, newObj) {
    let obj = newObj || {} 
    for (let i in oldObj) {
        if (oldObj[i] === obj) { // 防止循环引用
            continue
        }

        if (typeof oldObj[i] === 'object') {
            // obj[i] = (oldObj[i].constructor === Array) ? [] : {}
            obj[i] = oldObj[i] instanceof Array ? [] : {}
            deepCopy(oldObj[i], obj[i])
        } else {
            obj[i] = oldObj[i]
        }
    }
    return obj;
}

这样就能处理一个嵌套了Object和Array等复杂变量的对象。但是对象中还可能包含Date和RegExp对象、Set、Map……

Lodash库

const lodash = require('lodash')
let newObj = lodash.cloneDeep(obj)


数组的复制

let arr = [1, 2, 3, [4, 5], {a: 1}]

let copy = arr
copy.push(6)

let copy1 = [...arr]
copy1.push(999)

let copy2 = Array.from(arr)
copy2.push(888)

let copy3 = arr.slice()
copy3.push(777)

// 以上方法都是浅拷贝
arr[4].a = 2

console.log(arr)   // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6 ]
console.log(copy1) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6 ]
console.log(copy2) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 888 ]
console.log(copy3) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 777 ]


链接: https://www.fly63.com/article/detial/6245

js中深拷贝和浅拷贝的区别及原理

javascript的深拷贝和浅拷贝主要是针对像Object, Array这样的复杂对象的,简单理解为浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。

使用JSON.parse(),JSON.stringify()实现对对象的深拷贝

JSON.parse(),JSON.stringify()实现对对象的深拷贝以及兼容性问题,根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字符串会新辟一个新的存储地址,这样就切断了引用对象的指针联系。

使用jquery克隆对象_实现深、浅拷贝的简单实例

克隆JavaScript对象,首页想到的是obj = eval(uneval(obj)),但这是非标准的,推荐使用jquery提供的jQuery.extend方法,因为它包含了一些额外的类型验证逻辑,并且不会复制未定义的属性等。

JS中如何进行对象的深拷贝

在JS中,一般的=号传递的都是对象/数组的引用,并没有真正地拷贝一个对象,那如何进行对象的深度拷贝呢?对象的深拷贝与浅拷贝的区别如下:浅拷贝:仅仅复制对象的引用,而不是对象本身;深拷贝:把复制的对象所引用的全部对象都复制一遍。

javascript实现数组或对象的深拷贝

可以看出来,改变原数组arr,并没有对新数组copyArr产生影响;改变新数组copyArr也没有对原数组arr产生影响;同样:改变原数组arr,并没有对新数组copyArr产生影响;改变新数组copyArr也没有对原数组arr产生影响;

关于内存拷贝(浅拷贝)和js链表的小知识点

记录一个做leetcode看答案学到的小知识。。。浅拷贝实现一些特殊的功能的一些应用场景,比如:我们有一个需求如下

js的浅拷贝 VS 深拷贝

我们常常会用到拷贝对象的功能,而拷贝有浅拷贝和深拷贝2种。这篇文章会着重讲2个方面:1: 浅拷贝和深拷贝的区别2: 浅拷贝和深拷贝的具体实现,拷贝我们常常用在把A对象的属性copy到B对象,这样B对象就拥有了A对象的属性。

理解JS中的深拷贝与浅拷贝

了解深拷贝也不仅仅是为了应付面试题,在实际开发中也是非常有用的。例如后台返回了一堆数据,你需要对这堆数据做操作,但多人开发情况下,你是没办法明确这堆数据是否有其它功能也需要使用,直接修改可能会造成隐性问题

14个JS数组拷贝技巧

数组拷贝经常被误解,但这并不是因为拷贝过程本身,而是因为缺乏对 JS 如何处理数组及其元素的理解。JS 中的数组是可变的,这说明在创建数组之后还可以修改数组的内容。这意味着要拷贝一个数组,咱们不能简单地将旧数组分配给一个新变量

JS变量存储与深拷贝和浅拷贝

string、number、null、undefined、boolean、symbol(ES6新增) 变量值存放在栈内存中,可直接访问和修改变量的值 基本数据类型不存在拷贝,好比如说你无法修改数值1的值

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!