前言
深浅抄知识在我们的日常开发中还是用的比较多的,但是之前的状态一直是听说过从来没用过(其实我也没意识到),所以今天就跟大家说说js的深浅抄;
首先,让我们来看看javascript的数据类型。在js版本的ES5中,javascript有六种数据类型,它们是:
数字(数字类型)、字符串(字符串)、布尔(布尔类型)、对象(对象,对象和数组都属于对象类型)、空值和未定义
我们日常使用的javascript深浅副本主要是为了复制Object引用类型;
我们知道js的深度和浅度副本面临着什么,然后让我们看看深度和浅度副本的概念:
复制,顾名思义,就是复制。内存分为两个区域:堆栈内存和堆内存。所谓的深、浅拷贝主要是拷贝javascript引用类型数据,浅拷贝是在引用类型数据相互赋值之后,例如obj 1=obj 2;如果obj1或obj2在以下操作中被修改,此时数据将相应地改变,因为内存中的引用类型数据存储在堆内存中,堆内存存储引用类型值。同时会有一个指向栈内存的指针地址,两个引用类型的数据地址相同。一个改变,另一个就会有影响;深度副本不会,深度副本将在堆内存中重新打开一个空间进行存储;
基本类型复制:
var a=1;var b=a;//复制console . log(b)//1a=2;//更改一个console . log(b)//1 console . log(a)//2由于a和b都属于基本类型,基本类型的复制不会相互影响,因为每次一个基本类型创建一个变量时,都会在栈内存中打开一块内存来存储该值,所以复制基本类型不会影响另一个变量;
引用类型的副本:
引用类型的复制分为两个方面:阵列复制和对象复制:
js :的浅拷贝
var arr1=['红色','绿色'];var arr2=arr1//复制console.log (arr2)//['红色','绿色'];arr 1 . push(' black ');//更改color1 console.log (arr2)//['red ',' green ',' black']console . log(arr 1)/[' red ',' green ',' black ']上例是javascript数组的浅拷贝。从上面的知识中,我们可以看出数组是引用类型的数据。引用类型数据的复制会相互影响。我们看到arr1.push('black ')增加了一个新的子项,因为上面的代码var arr2=arr1将两个引用类型数据的地址指针指向同一个堆内存区域,所以无论arr1还是arr2被修改,两个数组的任何一个变化都会对彼此产生影响。上面的直接赋值方法的副本是我们常说的引用类型的浅拷贝;
关于深度复制很多同学误以为js的原生方法concat和slice属于深度复制,其实不然;Js的原生方法concat和slice只适用于一维数组。一旦它们以二维数组或多维数组的形式到达,就会出现问题,不完整的复制会导致数据的相互牵引;
slice:
var arr1=['红色','绿色'];var arr 2=arr 1 . slice(0);//复制console.log (arr2)//['红色','绿色'];arr 1 . push(' black ');//更改color1 console.log (arr2)//['red ',' green ']console . log(arr 1)/[' red ',' green ',' black'] JS的本机方法切片将返回一个新数组。乍一看,上面的代码会被认为是深度拷贝,因为arr2和arr1是的,这符合深度拷贝的特点,但是拷贝不够彻底,所以不能被认为是真正意义上的深度拷贝,所以切片只能称为浅拷贝;切片法只适用于一维数组的复制,在二维数组中会充满瑕疵;
让我们看一下二维数组的例子:
var arr1=[1,2,3,['1 ',' 2 ',' 3 ']];var arr 2=arr 1 . slice(0);arr 1[3][0]=0;console . log(arr 1);//[1,2,3,['0 ',' 2 ',' 3 ']]console . log(arr 2);//[1,2,3,['0 ',' 2 ',' 3']]上面的代码是一个二维数组。当我们改变arr1[3][0]中arr1的值时,我们发现arr1和arr2的值发生了变化。所以事实证明,切片不是深度拷贝;
concat:
var arr1=['红色','绿色'];var arr 2=arr 1 . concat();//复制console.log (arr2)//['红色','绿色'];arr 1 . push(' black ');//更改color 1 console . log(arr 2)/[' red ',' green ']console . log(arr 1)/[' red ',' green ',' black'] var arr1=[1,2,3,['1 ',' 2 ' var arr 2=arr 1 . concat();arr 1[3][0]=0;console . log(arr 1);//[1,2,3,['0 ',' 2 ',' 3 ']]console . log(arr 2);//[1,2,3,['0 ',' 2 ',' 3']]concat方法不会影响一维数组中源数组的数据,而concat性能与二维数组中切片相同;
js的深层副本:
在js数组中实现深度复制的方法有很多,比如JSON。解析(JSON。stringfy())和递归,以及JQuery库的extend方法(只有extend方法依赖于JQuery库,所以我们尽量用原生方式实现),可以实现数组和对象的深度复制。
var arr1=['红色','绿色'];var arr 2=JSON . parse(JSON . stringify(arr 1));//复制console.log (arr2)//['红色','绿色'];arr 1 . push(' black ');//更改color1 console.log (arr2)//['red ',' green ']console . log(arr 1)/[' red ',' green ',' black']我们可以清楚地看到,在上面的代码中,JSON.parse(JSON.stringify())是真正意义上实现的
深度复制的递归实现;
函数deepClone(obj){ //确定该参数是否是一个对象,让objclone=object的objinsity。[]:{};If (obj的obj类型==' object '){ for(obj中的键){if (obj。hasown property(key)){//判断ojb子元素是否是对象,如果是,递归复制if(obj[key]=' object '){ obj } else {//如果不是,简单复制objClone[key]=obj[key];} } } }返回objClone} var a={ x:1,y :2 };b=DeepCrone(a);a . x=3 con sole . log(a);console . log(b);输出效果如下:
总结:
1:深度复制只从源数据复制一个副本进行操作,不改变源数据;它是一个改变源数据的浅拷贝;
2.原生js方法slice和concat不是真正意义上的深度复制,它们只适用于一维数组,复制的属性不够彻底;
3.要实现js深度复制,可以通过JSON来实现。解析(JSON。stringfy()),JQuery库的递归和扩展方法。
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。