浅拷贝和深拷贝

浅拷贝和深拷贝

拷贝数据:

  • 拷贝基本数据类型(String,Boolean,Number,平时主要用到的值类型),它会生产一份新的数据,对拷贝后生成的数据进行修改不会影响到原数据的;
  • 拷贝引用数据类型(Array,Object,function),它不会生成新的数据,而是拷贝了一份数据在堆中的地址引用,对拷贝后生成的数据进行修改则会影响到原数据的;
  • 拷贝数组或对象后,修改拷贝后的数据会影响到原来数据的拷贝被称为浅拷贝,反之称为深拷贝
// 不会影响到原数据
let str = 'abcd';
let str2 = str;//拷贝字符串
console.log(str2);//'abcd'
str2 = '';// 不会影响到原数据
console.log(str,str2);//'abcd',''

let bool1 = true;
let bool2 = bool1;//拷贝boolean
console.log(bool2);//true
bool2 = false;// 不会影响到原数据
console.log(bool1,bool2);//true , false

let obj1 = {username:'curry', age: '22'};
let obj2 = obj1;//拷贝对象
console.log(obj2);//{username:'curry', age: '22'}
obj2.username = 'tomphson';//修改数据影响到了原数据
console.log(obj1,obj2);//{username:'tomphson', age: '22'} ,{username:'tomphson', age: '22'} 

let arr1 = [1,4,{username:'curry', age: '22'}];
let arr2 = arr1;//拷贝数组
arr2[0]='abcd';//修改数据影响到了原数据
console.log(arr1);//['abcd',4,{username:'curry', age: '22'}]


拷贝数据的方法:

  • 直接赋值给一个变量 //拷贝数组和对象就是浅拷贝
  • Object.assign({},obj); //浅拷贝
  • Array.prototype.concat(); //浅拷贝
  • Array.prototype.slice(); //浅拷贝
  • JSON.parse(JSON.stringify()); //深拷贝,但无法拷贝函数,因为stringify方法要求放入的数据是原生js对象和数组
// Object.assign({},obj); 
let obj1 = {username:'tomphson', age: '22'} ;
let obj2 = Object.assign(obj1);//浅拷贝
obj2.username = 'curry';
console.log(obj1.username);//'curry'

//Array.prototype.concat();     
let arr1 = [1,2,{username:'curry'}];
let arr2 = arr1.concat([]);
console.log(arr2);//[1,2,{username:'curry'}]
arr2[1]='abcd';//这里修改的是基本数据类型,不会影响到原数据
arr2[2]={username:'tomphson'};//修改的是对象则会影响原数据
console.log(arr1);//[1,2,{username:'tomphson'}]

//Array.prototype.slice();  
let arr3 = arr1.slice(0,0);
arr3.username ='curry';
console.log(arr1);//[1,2,{username:'curry'}]

//JSON.parse(JSON.stringify()); 
let arr4 = JSON.parse(JSON.stringify(arr1));
arr4.username = 'tomphson';
console.log(arr1);//[1,2,{username:'curry'}]

深度拷贝原理和实现

  • 因为拷贝基本数据类型不会影响到原来的数据,因此我们可以根据这点遍历拷贝对象判断其数据类型直到不是引用数据类型来实现深度拷贝
/*
实现深度拷贝,则需要判断数据类型和遍历对象
判断数据类型的方法:
	typeof返回的数据类型:string,number,boolean,undefined,object,function
	Object.prototype.toString.call(obj)
遍历对象 for in
*/
let result = ['abcd'];
console.log(Object.prototype.toString.call(result));//[object Array] 需要截取字符串

// 定义检测数据类型的功能函数
function checkType(target) {
    return Object.prototype.toString.call(target).slice(8, -1);
}
function deepClone(target) {
    let targetType = checkType(target),
        result;//初始化变量result成为最终克隆的数据
    //判断数据类型是否为数组或对象
    if(targetType === 'Array') {
        result = [];
    }else if(targetType === 'Object') {
        result = {};
    }else {
        // 基本数据类型
        result = target;
        return result;
    }
    // 遍历目标数据
    for(let key in target) {
        let value = target[key],
            valueType = checkType(value);
        //判断目标结构里的每一项数据是否存在数组/对象
        if( valueType === 'Array' || valueType==='Object') {
            // 继续遍历
            result[key] = deepClone(value);
        }else {
            result[key] = value;
        }
    }
    return result;
}
//验证
let arr1 = [1,2,{username:'curry'}];
let arr2 = deepClone(arr1);
arr2.username = 'tomphson';
console.log(arr1);//[1,2,{username:'curry'}];
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值