JS 深浅拷贝的原理以及实现方法


前言

JS 的深浅拷贝是面试常问的一道题,实际做项目中也会经常遇到一些深拷贝的用法,或者有时候在使用VUE的双向数据绑定时,会发现不生效,可能就是因为没有进行深拷贝,不能改变传值过来的数据问题呢!!!!! 在理解什么是首先拷贝时,首先要清楚JS的数据类型有哪些

一、JS的数据类型以及他们的区别

JS 的数据类型主要有两种,分别为引用数据类型和基本数据类型两种。
1.常见的基本数据类型主要有:Number,String,Null,Boolean,Undefined 这五种。另外ES6中有一个新的基本数据类型:Symbol。想了解的可以详细看下这个类型,这里不详细解释了。链接: symbol.
2. 常见的引用数据类型:也就是对象类型Object type,比如:Object 、Array 、Function 等。
3. 他们之间的区别:
⑴基本的数据类型主要存放在内存的栈中,引用数据类型的数据存放在堆中,但是他的引用地址是存放在栈中。
所谓的深浅拷贝主要就是针对引用数据类型来说的,浅拷贝其实就是拷贝数据的引用地址,拷贝出的数据还是和原数据共用一块内存堆,在改变新数据的时候原始数据也会发生变化。
深拷贝是能够实现引用数据类型的真正拷贝,它是在内存堆中新开辟了一块空间,把原来的数据拷贝过去一份,实现数据的拷贝。

二、常见的浅拷贝方法

1.浅拷贝

代码如下(示例):
(1)

 var obj = {
        name: '张三',
        age: 18,
        friends: ['Kate', 'Bob', 'Mike'],
        hobby: {
            hobby1: 'codes',
            hobby2: 'piano'
        }
    }

    function copy(data) {
        var obj = {};
        for (var key in data) {
            obj[key] = data[key]
        }
        return obj;
    }
    var CopyObj = copy(obj);
    console.log(CopyObj.friends); //["Kate", "Bob", "Mike"]
    obj.friends.push('lisi');
    console.log(CopyObj.friends) //["Kate", "Bob", "Mike", "lisi"]
可以看出 实现数据的拷贝之后,在改变原数据的时候新拷贝的数据的值也会发生相应的变化

(2)使用ES6 assign 也可以实现数据的快速浅拷贝

	var obj3 = Object.assign(obj);
	  
    console.log(obj3.friends) //["Kate", "Bob", "Mike"]

2.深拷贝

常见方法:
(1)使用JSON 对象实现深拷贝

    var obj3 = JSON.parse(JSON.stringify(obj))
    console.log(obj3.friends) //["Kate", "Bob", "Mike"]
    obj.friends.push('lisi')
    console.log(obj3.friends) //["Kate", "Bob", "Mike"]

可以看出实现了数据的深拷贝,但是有个缺陷,他无法对数据中的方法进行拷贝,会显示undefined

(2)通过jQuery的extend方法实现深拷贝

var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝

(3) 最常用的是手写一个递归进行数据的深拷贝

 function deepClone(source) {
      let targetObj;
      //判断是否为引用数据类型
      if (source && typeof source === "object") {
      //判断他的类型是数组还是对象,进行相应的赋值
        targetObj = source.constructor === Array ? [] : {};
        //Object.keys()返回值是数组,如果是对象,返回对象的key值,数组返回数组的索引值
        Object.keys(source).forEach((keys) => {
        //判断当前项是否为引用数据类型进行递归
          if (source[keys] && typeof source[keys] === "object") {
            targetObj[keys] = deepClone(source[keys]);
          } else {
            targetObj[keys] = source[keys];
          }
        });
      } else {
        throw new Error("error arguments", "deepClone");
      }
      return targetObj;
    },

总结

总体来说:只要掌握了数据的类型以及理解他们的存储位置,数据的深浅拷贝原理都大概清楚。实现方法主要还是用到递归实现,一般面试问到也主要是考递归这一层。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值