值类型和引用类型,深层复制和浅层复制(深拷贝浅拷贝)最详细了

时间:2020-12-11 19:50:24

要知道深层复制浅层复制的区别,首先要了解值类型和引用类型。

变量分值类型和引用类型,深层复制和浅层复制都是针对引用类型变量的操作。

值类型: 比如数值,字符串,布尔,undifined

引用类型 : 比如数组,对象,函数

来张图(手抖,有点丑):

值类型和引用类型,深层复制和浅层复制(深拷贝浅拷贝)最详细了

var num = 77;

var id = 1234;

var cat = {name : '喵喵',age : 3 };

结合上面图,内存分两块区域,栈和堆。

值类型的数据保存在栈中;

引用类型的存储需要栈和堆共同完成,在栈中存放地址,该地址指向对应的堆内存中的数据。

看看区别

值类型:

    var  name = '周小七';

    var  other= name ;

    name = '周小八'

    console.log(other) ; //'周小七'

   console.log(name == other) ;//false

引用类型:

    var seven1 = {};

    var seven2 = seven1;

    seven1.name = '周小七';

    console.log(seven2.name); //'周小七'

     console.log(seven1 == seven2);//true

为什么? 因为他们都是指向同一个对象的,再来个丑图,哈哈:

值类型和引用类型,深层复制和浅层复制(深拷贝浅拷贝)最详细了

基础讲完,开始看拷贝:

对象的实例是存储在堆内存中然后通过一个引用值去操作对象,由此拷贝的时候就存在两种情况了:拷贝引用和拷贝实例,这也是浅拷贝和深拷贝的区别。

浅拷贝

以上面的为例,var seven2 = seven1,这就是浅层复制,拷贝之后,seven1===seven2,这是浅拷贝的一种情况,直接拷贝源对象的引用,另外一种情况有点复杂,拷贝源对象的实例,但如果其属性值为复杂的数据类型,只拷贝其内层元素的引用,啥意思?上代码:

var a = [{m:1}, {n:2},3]; 
var b = a.slice();
console.log(b);//[{m:1}, {n:2},3]
console.log(a === b);// false
a[0].m = 4;
console.log(b[0].m)//4,说明拷贝的是元素的引用
a[2] = 5;
console.log(b[2])//3,说明拷贝的实例,(拷贝的a上面的3)

我拷贝你的时候,你里面属性值是值类型的,我直接拷走,你值类型再变化,我不受影响;你里面的属性值如果是复杂一些的引用类型,太重了,我拷不走,那我就只拷贝指向它的地址,当你这边值变化时,我那边也跟着变。一句话概括就是,看人下菜碟。哈哈哈,势利眼。。。。


深拷贝

深拷贝是克隆了一个一模一样的对象,目标是使 seven1 != seven2,深拷贝会开辟新的内存区域,地址指向不同的地方。深拷贝后的对象与原来的对象是完全隔离,互不影响

深拷贝怎么实现?

1. 来个最简单粗暴的(我个人常用),哈哈:

seven2 = JSON.parse(JSON.stringify(seven1));

大部分的时候可以用,局限:函数不能复制;原型链搞没了...

2. jQuery.extend() : 用于将一个or多个对象内容合并到目标对象:

$.extend( [deep ], target, object1 [, objectN ] )

deep默认false---浅拷贝(第二种浅拷贝,拷贝实例,内层属性值引用类型时,只拷贝内层元素的引用

deep设置true---深拷贝,上代码:

 
var a = [{m:1}, {n:2},3]; 
var b =[];
$.extend(true,b,a);
console.log(a === b);// false
a[0].m = 4;
console.log(b[0].m)//1
a[2] = 5;
console.log(b[2])//3

这样无论a再怎么变化,都不会影响到b了。

呼~~完事,写的不能再详细了赶脚~,还画图简直累死宝宝惹,o(╥﹏╥)o~