浅谈——JS深浅拷贝

浅谈深浅拷贝

最近和人聊起到深浅拷贝的问题,感触有点,觉得这个问题可深可浅,面试经常会遇到深浅拷贝的问题,主要考察你对数据类型的掌握理解,不过很多人对这块也说的不是很清晰,今天就简单来谈谈我的个人看法

说到深浅拷贝就必须要提到数据类型的内存存储方式

在js引擎中对数据的存储主要有两种位置,栈内存和堆内存。

数据分为:

  1. 基本数据类型(String, Number, Boolean, Null, Undefined,Symbol(new in ES 6)
  2. 引用数据类型(统称为 Object 类型,细分的话有:Object 、Array 、Date 、RegExp、Function… )。

在这里插入图片描述
特点:
1、 基本数据类型的特点:直接存储在栈(stack)中的数据
2、 引用数据类型的特点:将该对象引用地址存储在栈中,然后对象里面的数据存放在堆中。
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

切入主题,在我看来,深浅拷贝就是传值和传址的问题,它主要针对的是引用类型数据

浅拷贝:只拷贝某个对象的指针而不拷贝对象本身,即他们的指针指向同一内存空间,也就是说,只要你更改了拷贝对象的数据,那内存空间里的数据即被更改,原来的数据也会跟着被更改。

// 定义变量
let aObj = {
    uname: 'z3',
    age: 18
}

// 浅拷贝
let bObj = aObj

// 输出 -> 修改 -> 输出
console.log(aObj.uname)  //z3
console.log(bObj.uname)  //z3

bObj.uname = 'l4'

console.log(aObj.uname)  //l4
console.log(bObj.uname)  //l4

深拷贝:拷贝某个对象,并且在内存中开辟一个新的内存空间,指针指向新的内存空间,即修改它的值,不影响原来对象的数据。

// 定义变量
let a = 666

// 浅拷贝
let b = a

// 输出 -> 修改 -> 输出
console.log(a)  //666
console.log(b)  //666

b = '777'

console.log(a)  //666
console.log(b)  //777

总结优缺点:

浅拷贝:不会造成内存的浪费,但是在某些复杂灵活的环境中,例如一个对象在多出被用到,在某一处不小心修改了其数据,其他地方就很难预见数据是如何改变的,这时候需要使用深拷贝来解决问题
深拷贝:解决了浅拷贝的问题,但是又造成了内存的浪费

如何将浅拷贝转为深拷贝,有几种方法
1、展开运算符(有瑕疵,只针对简单数据有效,复杂多维无效)
2、Object.assign() 有瑕疵,同上
3、JSON的解析方式

JSON.parse(JSON.stringify(obj))

4、递归方法

function deepCopy(obj) {
    var result = Array.isArray(obj) ? [] : {};
    for (var key in obj) {
        if (typeof obj[key] === 'object' && obj[key] !== null) {
            result[key] = deepCopy(obj[key]) //递归复制
        } else {
            result[key] = obj[key]
        } 
    }
    return result
}
let b = deepCopy(a)

5、lodash模块 (详情https://www.npmjs.com/package/lodash
6、immutable模块 (详情https://www.npmjs.com/package/immutable

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值