Js实现深浅复制

时间: 2019-11-02阅读: 314标签: 拷贝

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

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 ]


站长推荐

1.阿里云: 本站目前使用的是阿里云主机,安全/可靠/稳定。点击领取2000元代金券、了解最新阿里云产品的各种优惠活动点击进入

2.腾讯云: 提供云服务器、云数据库、云存储、视频与CDN、域名等服务。腾讯云各类产品的最新活动,优惠券领取点击进入

3.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

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

在JavaScript 中 14 个拷贝数组的技巧

数组拷贝经常被误解,但这并不是因为拷贝过程本身,而是因为缺乏对 JS 如何处理数组及其元素的理解。JS 中的数组是可变的,这说明在创建数组之后还可以修改数组的内容。

14个JS数组拷贝技巧

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

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

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

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

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

JS对象复制(深拷贝、浅拷贝)

注意: 此方法仅在原对象包含可序列化值类型且没有任何循环引用时才有效。不可序列化值类型的一个例子是 Date 对象 - JSON.parse 只能将其解析为字符串而无法解析回其原始的 Date 对象 或者对象中属性值为function

JavaScript 中对象的深拷贝

在JavaScript中,对对象进行拷贝的场景比较常见。但是简单的复制语句只能对对象进行浅拷贝,即复制的是一份引用,而不是它所引用的对象。而更多的时候,我们希望对对象进行深拷贝,避免原始对象被无意修改。

js的浅拷贝 VS 深拷贝

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

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

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

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

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

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

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

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

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全运营推广