关于前端:JS-深拷贝详解

10次阅读

共计 1619 个字符,预计需要花费 5 分钟才能阅读完成。

1. 这里实现了深拷贝是因为在根本数据类型 String Number 都能够实现深拷贝因为它只有一层,且每次扭转的变量的值都是扭转整个变量这样在堆中又开拓了一个内存空间,没有嵌套的状况下间接批改整个变量的办法在对象和办法中也实用
var a = 1
var b = a
a 打印后果为 1
b 打印后果为 1
a = 2
a 打印后果为 2
b 打印后果为 1

2. 这里实现了深拷贝的起因与第 1 条是一样的,因为改成 a 变量整个值,所以在堆中又开拓了一个新空间
var a = [1,2,3]
var b = a
a 打印后果为 (3) [1, 2, 3]
b 打印后果为 (3) [1, 2, 3]
a = [3,2,1]
a 打印后果为 (3) [3, 2, 1]
b 打印后果为 (3) [1, 2, 3]

3. 这里没有实现深拷贝是因为 这里的 a 是援用数据类型,且批改 a 的值时扭转的是下标 0 的数据,并没有整个 a 变量全副批改,所以并没有开拓新的内存空间,导致 a 和 b 都指向了同一个堆,故而打印的后果是一样的
var a = [1,2,3]
var b = a
a 打印后果为 (3) [1, 2, 3]
b 打印后果为 (3) [1, 2, 3]
a[0] = 2
a 打印后果为 (3) [2, 2, 3]
b 打印后果为 (3) [2, 2, 3]

4. 这里实现了深拷贝是因为给 b 赋值的时候应用了扩大运算符,这样就等于为 b 在堆外面新开了一个内存空间,故而实现了深拷贝
var a = [1,2,3]
var b = […a]
a 打印后果为 (3) [1, 2, 3]
b 打印后果为 (3) [1, 2, 3]
a[0] = 2
a 打印后果为 (3) [2, 2, 3]
b 打印后果为 (3) [1, 2, 3]

5. 这里应用了扩大运算符然而却没有像第 4 条那样实现深拷贝,因为这里的 a 是二维数组,a 和 b 下标为 3 的数据来源于同一个堆,故而打印后果为一样
var a = [1,2,3,[4,5]]
var b = […a]
a 打印后果为 [0:1,1:2,2:3,3:[0:4,1:5]]
b 打印后果为 [0:1,1:2,2:3,3:[0:4,1:5]]
a3 = 6
a 打印后果为 [0:1,1:2,2:3,3:[0:6,1:5]]
b 打印后果为 [0:1,1:2,2:3,3:[0:6,1:5]]

依据以上论断咱们得出结论:

        1. 无论是不是应用了扩大运算符只有是间接批改了 a 变量整体数据那就不影响 b,因为变量整体批改的话相当于在堆外面新开拓了一个内存
        2. 扩大运算符反对深拷贝只建设在没有嵌套数据的状况下。

上面咱们来说遇到多层嵌套的状况下怎么进行深拷贝

  1. 应用 JSON.stringify 转换为 JSON 字符串 后应用 JSON.parse 解析为 JS 的对象或值
    var a = [1,2,3,[4,5]]
    var b = JSON.parse(JSON.stringify(a))
    a 打印后果为 [0:1,1:2,2:3,[0:4,1:5]]
    b 打印后果为 [0:1,1:2,2:3,[0:4,1:5]]
    a3 = 11
    a 打印后果为 [0:1,1:2,2:3,[0:4,1:11]]
    b 打印后果为 [0:1,1:2,2:3,[0:4,1:5]]

2. 然而须要留神的是,JSON.stringify 无奈深拷贝函数。如下代码
var a = {function(){console.log(‘hello’)}}
a 打印后果为 {function: ƒ}
var b = JSON.parse(JSON.stringify(a))
b 打印后果为 {}

3. 这个时候咱们就须要用到递归遍历对象并手动进行拷贝 或者 Lodash 的_.cloneDeep 办法。函数序列化并还原是相当简单的操作,并且有平安危险,因为还原的函数将在不受管制的上下文中执行。应审慎应用和解决蕴含函数的序列化数据
const _ = require(‘lodash’);

const obj = {func: function() {console.log(‘Hello!’); } };
const clonedObj = _.cloneDeep(obj);
console.log(clonedObj);
// 输入: {func: [Function: func] }

正文完
 0