JS 深浅拷贝

简介

  • 浅拷贝:拷贝基本数据类型的值,但对于引用数据类型,只拷贝他在堆内存中的地址,修改新数据或者原数据都会引起原数据的改变
  • 深拷贝:把所有数据都赋值到新的内存空间,是最彻底的拷贝

浅拷贝方法

1.Object.assgin()

对数据进行浅拷贝,可以将多个源对象拷贝到一个新对象里去

// 语法1
const obj2 = Object.assgin({}, obj1);

// 语法2
Object.assign(目标对象, 源对象1, 源对象2...);

重点看这个

const obj1 = {
    name: 'qianguyihao',
    age: 28,
    desc: 'hello world',
};

const obj2 = {
    name: '许嵩',
    sex: '男',
};

// 浅拷贝:把 obj1 赋值给 obj2。这一行,是关键代码。这行代码的返回值也是 obj2
Object.assign(obj2, obj1);

console.log(JSON.stringify(obj2));

2.for in 方法(繁琐不推荐)

const obj1 = {
    name: 'qianguyihao',
    age: 28,
    info: {
        desc: '很厉害',
    },
};

const obj2 = {};
//  用 for in 将 obj1 的值拷贝给 obj2
for (let key in obj1) {
    obj2[key] = obj1[key];
}

console.log('obj2:' + JSON.stringify(obj2));

obj1.info.desc = '永不止步'; // 当修改 obj1 的第二层数据时,obj2的值也会被改变。所以  for in 是浅拷贝

console.log('obj2:' + JSON.stringify(obj2));

深拷贝方法

深拷贝就是对浅拷贝的递归

1. JSON.parse(JSON.stringify())

原理:用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝

let arr = [1, 3, {
    username: ' kobe'
}];

let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
console.log(arr, arr4)

这种方法虽然可以实现数组或对象深拷贝,但不能处理函数

let arr = [1, 3, {

    username: ' kobe'

},function(){}];

let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
console.log(arr, arr4)
// [ 1, 3, { username: ' kobe' }, [Function (anonymous)] ]
// [ 1, 3, { username: 'duncan' }, null ]

这是因为JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数

2.函数库lodash

var _ = require('lodash');

var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};

var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);

// false

3. for in 实现深拷贝

let obj1 = {
    name: 'qianguyihao',
    age: 28,
    info: {
        desc: 'hello',
    },
    color: ['red', 'blue', 'green'],
};
let obj2 = {};

deepCopy(obj2, obj1);
console.log(obj2);
obj1.info.desc = 'github';
console.log(obj2);

// 方法:深拷贝
function deepCopy(newObj, oldObj) {
    for (let key in oldObj) {
        // 获取属性值 oldObj[key]
        let item = oldObj[key];
        // 判断这个值是否是数组
        if (item instanceof Array) {
            newObj[key] = [];
            deepCopy(newObj[key], item);
        } else if (item instanceof Object) {
            // 判断这个值是否是对象
            newObj[key] = {};
            deepCopy(newObj[key], item);
        } else {
            // 简单数据类型,直接赋值
            newObj[key] = item;
        }
    }
}

参考文章:JS 深浅拷贝

上一篇:【Java】弱引用的相关使用


下一篇:JS内存管理