JS浅复制和深复制

在JS里面,俗话说“万物皆对象”,那么对于引用型对象的复制,就存在浅复制和深复制的问题。

(注意:js基本数据类型变量不存在浅复制和深复制问题)

1、浅复制

     对象引用变量的的复制,复制操作之后的两个变量会相互影响,一个的变量的值改变了,另一个变量的值也会随之改变。

2、深复制

     产生一个对象的副本,完全独立于原来的对

象,副本的属性发生改变并不会影响原来的对象的属性。

3、出现浅复制和深复制的深层原因

     计算机利用堆栈存储数据信息,栈内存比较小,但在栈内存中访问数据速度很快,堆内存容量比较大,但访问速度相对较慢。

JS基本数据类型数据简单,直接存储在栈内存里,而引用型对象

会在栈内存中存引用指针变量(指向对象实体在堆内存的地址)。

   3.1 JS基本数据类型:

let a=123;
let b=a;
b=456;
console.log(b);
//456
console.log(a);
//123
栈内存存储基本数据类型
变量名
a123
b123

   直接存储在栈中,值的改变不会相互的影响。

 3.2 JS引用数据类型

class Person{
    constructor(name,age){
		this.name=name;
		this.age=age;
	}
}
let p1=new Person("zhangsan",123);
let p2=p1;
p2.name="lisi";

console.log(p1.name);
//lisi

在计算机堆栈中p1和p2的情况如下:

栈内存引用数据
变量
p1堆地址1
p2堆地址1
堆内存存储引用数据
地址对象实体
堆地址1{ name:"zhangsan",age:123 }
  

     每次取对象的属性时,先判断是否是简单数据类型,若为简单数据类型,计算机在栈中直接找到变量对应的值;若为引用数据类型,计算机先在栈内存中找变量对应的值(即堆地址编号),然后再根据该值(堆地址编号)去堆找到对应的实体,接着进行后续的操作。

 

4、浅复制和深复制的应用场景

     4.1 基本数据类型复制:直接赋值,不用考虑浅复制和深复制。

     4.2 引用数据类型:

           4.2.1浅复制:直接通过赋值进行复制,传递对象的引用。

           例如: 数组的复制:

let  a=['mary','kangkang','michael'];
let  b=a;
console.log(b);
//['mary','kangkang','michael']

   注意:数组的slice()方法和concat()方法等,并没有进行深复制,只是复制了对象的一层属性。 

let a=[1,2,3];
let b=[a,4,5,6];
let c=b.slice(0);
a.push(100);
console.log(a);
//[1,2,3,100]
console.log(c);
//[[1,2,3,100],4,5,6],a的值发生改变,c的值也会发生改变,所以c并没有对b进行深层复制。

     4.2.2 深复制:很多时候需要堆对象进行复制,将对象的所有属性重新拷贝一份,之后完全独立于原对象。

  function getType(obj){
       //tostring会返回对应不同的标签的构造函数
       let toString = Object.prototype.toString;
       let map = {
          '[object Boolean]'  : 'boolean', 
          '[object Number]'   : 'number', 
          '[object String]'   : 'string', 
          '[object Function]' : 'function', 
          '[object Array]'    : 'array', 
          '[object Date]'     : 'date', 
          '[object RegExp]'   : 'regExp', 
          '[object Undefined]': 'undefined',
          '[object Null]'     : 'null', 
          '[object Object]'   : 'object'
      };
      if(obj instanceof Element) {
           return 'element';
      }
      return map[toString.call(obj)];
   }

function deepClone(data){
       let type = getType(data);
       let obj;
       if(type === 'array'){
           obj = [];
       } else if(type === 'object'){
           obj = {};
       } else {
           //不再具有下一层次
           return data;
       }
       if(type === 'array'){
           for(let i = 0, len = data.length; i < len; i++){
               obj.push(deepClone(data[i]));
           }
       } else if(type === 'object'){
           for(let key in data){
               obj[key] = deepClone(data[key]);
           }
       }
       return obj;
   }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值