当前位置:   article > 正文

深拷贝与浅拷贝_let a = { name: 'a' };let b = a;a.b = a = {name: '

let a = { name: 'a' };let b = a;a.b = a = {name: 'b'};

2、深拷贝与浅拷贝

看这一篇的时候建议先看一下上一篇关于数据类型的文章。

直接赋值

直接赋值:把对象a赋值给对象b,实际上是把对象b的地址指向对象a的对象。a与b的地址指针一样,指向同一个对象,所以修改b时,a也会跟着发生改变。注意,修改b的无论是对象属性(引用数据类型)还是非对象属性(基本数据类型),a都会跟着发生改变。

let a = {
	name:'a',
	arr:[1,2]	
}
let b = a;
b.name = 'b';
console.log(a.name);  //  b
b.arr = [1,3]
console.log(a.arr); // [1,3]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

浅拷贝

浅拷贝:赋值对象的非对象属性,对象a与对象b的地址指针不一样,不会指向同一个对象,对象b是一个新的对象。修改b的非对象属性,a的非对象属性不会跟着变化。但是修改b的对象属性,会影响a的对象属性。这是因为,在浅拷贝时如果是非对象属性(基本数据类型),那么拷贝的是这个非对象属性的值,如果拷贝的是对象属性(引用数据类型),那么拷贝的是地址指针,所以修改b的对象属性,会影响a的对象属性。

let a = {
	name:'a',
	other:{
		arr:[1,2]	
	}
	
}
let b = Object.assign({},a);
b.name = 'b';
console.log(a.name);  //  a
b.other.arr = [1,3]
console.log(a.other.arr); // [1,3]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

浅拷贝实现方法

注意如果object只有一层那么就是深拷贝。

1)Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。例子可以看上面。

2)引用复制
function shallowClone(copyObj){
	var obj = {}
	for(let i in copyObj){
		obj[i] = copy[i]
	}
	return obj
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3)Array.prototype.concat()
let a = [1,2,{name:'a'}]
let b = a.concat()
  • 1
  • 2
4)Array.prototype.slice()
let a = [1,2,{name:'a'}]
let b = a.slice()
  • 1
  • 2
深拷贝

深拷贝:拷贝一个一模一样的对象,对象a与对象b的地址指针不一样,不会指向同一个对象,对象b是一个新的对象,而且对象b与对象a不再共享内存。**无论修改b的非对象属性还是对象属性,a的非对象属性/对象属性都不会跟着变化。**这是因为对象b的对象属性与a对象的对象属性都不再指向同一个对象,即地址指针不一样。

let a = {
	name:'a',
	other:{
		arr:[1,2]	
	}
	
}
let b = JSON.parse(JSON.stringify(a));
b.name = 'b';
console.log(a.name);  //  a
b.other.arr = [1,3]
console.log(a.other.arr); // [1,2]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

深拷贝实现方法
1) JSON.parse(JSON.stringify())

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

弊端:
1、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;
2、如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象;
3、如果obj里有函数,undefined,symbol,则序列化的结果会把函数或 undefined,symbol丢失
4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null;
5、JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor
6、如果对象中存在循环引用的情况也无法正确实现深拷贝;

详情可见:关于JSON.parse(JSON.stringify(obj))实现深拷贝应该注意的坑

2) 递归拷贝
 function deepCopy(obj) {
	  if (obj=== null) return null;
      if (typeof obj!== 'object') return obj;
      var result = Array.isArray(obj) ? [] : {};

      for (var key in obj) {

        if (obj.hasOwnProperty(key)) {

          if (typeof obj[key] === 'object' && obj[key]!==null) {

            result[key] = deepCopy(obj[key]);   //递归拷贝

          } else {

            result[key] = obj[key];

          }

        }

      }

      return result;

    }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
3)函数库lodash
var lodash = require('lodash');
var obj1 = {
   a: 1,
   b: { b: { b: 1 } },
   c: [1, 2, 3]
};
var obj2 = lodash.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/68219
推荐阅读
相关标签
  

闽ICP备14008679号