深拷贝与浅拷贝

深拷贝和浅拷贝

相关知识介绍

1、javascript 变量包含两种不同数据类型的值:基本类型和引用类型。

​ 基本类型:number、string、boolean、null、undefined。

​ 引用类型值指那些可能由多个值构成的对象:object。

在将一个值赋给变量的时候,浏览器必须确定这个值是基本类型值还是引用类型值。

2、javascript的变量的存储方式:栈(stack)和堆(heap)。

​ 栈:自动分配内存空间,系统自动释放,里面存放的是基本类型的值和引用类型的地址

​ 堆:动态分配的内存,大小不定,也不会自动释放。里面存放引用类型的值。

3、基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。

引用类型的值是保存在内存中的对象。JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。 在操作对象时, 实际上是在操作对象的引用而不是实际的对象。

基本类型与引用类型最大的区别实际就是 传值与传址 的区别

​ 值传递:基本类型采用的是值传递。

​ 地址传递:引用类型则是地址传递,将存放在栈内存中的地址赋值给接收的变量。

理解

基本类型和引用类型数据拷贝的问题,再深一点就是栈内存和堆内存的区别

img

浅拷贝的时候如果数据是基本数据类型,那么就如同直接赋值那种,会拷贝其本身,如果除了基本数据类型之外还有一层对象,那么对于浅拷贝而言就只能拷贝其引用,对象的改变会反应到拷贝对象上;但是深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。

浅拷贝

浅拷贝就是拷贝了一层,除了对象是拷贝的引用类型,其他都是直接将值传递,有自己的内存空间的。

	function simpleClone(initalObj) {
    var obj = {};
    for ( var i in initalObj) {
        obj[i] = initalObj[i];
    }
    return obj;
}
 
var obj = {
    a: "hello",
    b:{
        a: "world",
        b: 21
    },
    c:["Bob", "Tom", "Jenny"],
    d:function() {
        alert("hello world");
    }
};
var cloneObj = simpleClone(obj);
 
console.log(cloneObj.a);
console.log(cloneObj.b);
console.log(cloneObj.c);
console.log(cloneObj.d);
 
//更改原对象中的a,b,c,d,看看拷贝过来的对象是否变化
cloneObj.a = "changed";
cloneObj.b.a = "changed";
cloneObj.b.b = 25;
cloneObj.c = [1, 2, 3];
cloneObj.d = function() { alert("changed"); };
console.log(obj.a);    //hello
console.log(obj.b);    //{a:"changed",b:25},事实上就是只有对象是拷贝的引用类型
console.log(obj.c);    //['Bob','Tom','Jenny']
console.log(obj.d);    //...alert("hello world")

img

深拷贝

转成 JSON 再转回来

​ 用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。

	var obj1 = { body: { a: 10 } };
	
    var obj2 = JSON.parse(JSON.stringify(obj1));
    obj2.body.a = 20;
    console.log(obj1);
    // { body: { a: 10 } }  沒被改到
    console.log(obj2);
    // { body: { a: 20 } }
    console.log(obj1 === obj2);
    // false
    console.log(obj1.body === obj2.body);
    // false

注意:深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。

​ 这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。

递归方法:

​ 可以实现数组和对象的深拷贝

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : {};            
      arguments.callee(prop, obj[i]);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}
var str = {};
var obj = { a: {a: "hello", b: 21} };
deepClone(obj, str);
console.log(str.a);

注意:当遇到两个互相引用的对象,会出现死循环的情况用

es6新增

Object.assign(target,source)

​ 第一个参数是目标对象,之后还可以跟一个或多个源对象。

​ 它会遍历一个或多个源对象可枚举的自有键并把它们复制到目标对象,最后返回目标对象 。

​ Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标 对象拷贝得到的是这个对象的引用。

		var obj1 = {
            a: "hello",
            b: {
            a: "hello",
            b: 21
            }
        };

        var cloneObj1= Object.assign({}, obj1);
        cloneObj1.a = "changed";
        cloneObj1.b.a = "changed";
        console.log(obj1.a);  //hello
        console.log(obj.b.a); // "changed"
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值