深拷贝和浅拷贝

1. js变量的存储方式

1.1 栈和堆

栈:自动分配内存空间,系统自动释放,里面存放的是基本数据类型的值和引用类型的地址
堆:动态分配的内存,大小不定,也不会自动释放。里面存放引用类型的值
例:

var str1 = 'qwe';
var str2 = str1;
str2 = 'asd';
console.log(str1, str2);//qwe asd
var obj1 = { name: 'obj1' };
var obj2 = obj1;
obj2.name = 'obj2';
console.log(obj1, obj2);
//{name: 'obj2'} {name: 'obj2'}

1.2 基本类型和引用类型的赋值

基本类型:赋值 赋的是真正的值
引用类型:赋值 赋的是引用类型的地址
例:

var num1=10;
var num2=10;
console.log(num==age);//true
var arr=[1,2,3]
var arr2=[1,2,3]
console.log(arr==arr2);//false

2. 浅拷贝和深拷贝

2.1 浅拷贝

传的是地址

2.1.1 数组

var arr1 = [1, 3, 5]
var arr2 = arr1;
arr2.push(7);
console.log(arr1);//[1,3,5,7]
console.log(arr2);//[1,3,5,7]

2.2 深拷贝

传的是值

2.2.1 for循环

var arr3 = [1, 3, 5]
var arr4 = [];
for (var i = 0; i < arr3.length; i++) {
    arr4.push(arr3[i]);
}
arr4.unshift(0);//添加
console.log(arr3, arr4);// [1, 3, 5]  [0, 1, 3, 5]

2.2.2 slice()

var arr5 = [2, 4, 6];
var arr6 = arr5.slice(0);
arr6.shift();//删除第一个
console.log(arr5, arr6)//[2,4,6] [4,6]

2.2.3 concat()

var arr7 = [5, 6, 7];
var arr8 = arr7.concat();
arr8.pop();//删除最后一个
console.log(arr7, arr8);//[5,6,7]  [5,6]

2.2.4 对象

var obj1 = {
    name: 'obj1',
    age: '20'
}
var obj2 = {};
for (k in obj1) {
    obj2[k] = obj1[k];
}
obj2.age = 100;
console.log(obj1, obj2);
//{name: 'obj1', age: '20'} {name: 'obj1', age: 100}

2.2.5 JSON.parse(JSON.stringify())

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

let arr=[1,2,3{username:'ming'}];
let arrSecond=JSON.parse(JSON.stringify(arr));
arrSecond[2].username='hong';
console.log(arr,arrSecond);
// [1, 2, 3, { username: 'ming' }]  
//[1, 2, 3, { username: 'hong' }]

但不能处理函数

let arr = [1, 2, { username: "haha" }, function () { }];
let arr2 = JSON.parse(JSON.stringify(arr));
arr2[2].username = 'heihei';
console.log(arr, arr2);

运行结果

2.2.6 手写递归方法

递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝

 var obj = {
        id: 1,
        name: 'andy',
        msg: {age: 18},
        color: ['pink', 'red']
    };
    var o = {};
    // 用递归的方式完成深拷贝
    // 封装函数
    function deepCopy(newobj, oldobj) {
        // 遍历oldobj的属性名
        for (var k in oldobj) {
            // 判断属性属于哪种数据类型
            // 1.获取属性值 oldobj[k]
            var item = oldobj[k];
            // 2.判断是否属于数组(因为数组也属于对象,所以必须先判断数组)
            if (item instanceof Array) {
                newobj[k] = []; // (1)先给newobj添加一个属性k,同oldobj里的k
                deepCopy(newobj[k], item) // (2)再用oldobj[k]赋值给newobj[k]
            } else if (item instanceof Object) {
                // 3.判断是否属于对象
                newobj[k] = {};
                deepCopy(newobj[k], item)
            } else {
                // 4.属于简单数据类型
                newobj[k] = item
            }

        }
    }
    deepCopy(o, obj)
    console.log(o);

输出结果

2.2.7 函数库

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值