深浅克隆(拷贝)

在前端项目开发中,很多情况下都是在操作数据,如果碰到复杂的数据,操作起来就比较困难了。

例如:vue中数据是双向绑定的,页面显示依赖vue实例中的数据驱动,当页面中输入新的数据后,vue实例中的数据也发生了改变。若要将vue实例中的数据当做参数发送请求的时候,接口所需数据跟vue实例中的数据不对应,需要进行修改或删除,那页面中显示的内容也会随着发生变化,为了避免这种情况发生,我们需要对原数据进行复制,对复制出来的数据进行操作,此时就要用到深拷贝和浅拷贝。

深拷贝和浅拷贝主要针对于引用类型数据,因为基本数据类型赋值后,改变新数据,不会影响到原来的数据;而引用数据类型赋值后,改变新数据,将会影响到原来的数据,此时应该使用深拷贝和浅拷贝定义出一个跟原数据一样但互不影响的数据。

注意:赋值操作和深拷贝浅拷贝不是一回事。

赋值

基本类型数据的赋值

基本数据类型包括:numberstringbooleanundefinednull,他们的赋值相对简单,且赋值后两个变量互不影响。

var a = 10;
var b = a;
a = 20;
console.log(a);
console.log(b);

此时的b10,因为将a赋值给b,是将a空间中的值复制了一份,放到了b空间中,改变a,只是在改变a空间,对b空间并没有影响。

基本类型赋值

引用类型数据的赋值

引用数据类型包括:ArrayObject,他们的赋值相对复杂,且赋值后两个变量共享一个数据内存空间,改变其中一个,另一个也会发生改变。

var arr = [1,2,3];
var brr = arr;
arr.push(4);
console.log(arr);
console.log(brr);

此时的brr也有4个元素,跟arr是一模一样的,因为将arr赋值给brr,是将arr中存储的数据空间地址复制了一份,放到了brr中,arrbrr共享同一个数据空间,所以改变其中一个的数据,另一个也会发生改变。

引用数据类型的赋值

深拷贝和浅拷贝的出现,就是为了解决这个问题。

浅拷贝

浅拷贝是将原数据中所有的数据复制一份,放到新的变量空间中,两个变量不共享一个内存地址。

对象浅拷贝

使用系统提供的构造函数Object上的assign方法。

语法:

Object.assign({},原对象)
// 返回新对象

例:

var obj = {
    name:"张三",
    age:12,
    gender:"男"
}
var pbj = Object.assign({},obj);
console.log(obj);
console.log(pbj);

此时的pbjobj是一模一样的

对象浅拷贝

但是objpbj两个变量中存储的数据空间地址是不一样的,例:

obj.name = '李四';
obj.age = 20;
console.log(obj);
console.log(pbj);

此时的pbj一点变化也没有,name键的值还是张三age键的值还是12,因为objpbj不共享数据的内存地址。

拷贝后内存地址不同

注意:如果对象中有数据的值是引用数据类型,在创建新对象的过程中,会将这个引用数据类型的地址也放到新对象中。

var obj = {
    name:"张三",
    age:12,
    gender:"男",
    wife:{
        name:"翠花",
        age:11
    }
}
var pbj = Object.assign({},obj);
obj.wife.gender = "女";
console.log(obj.wife);
console.log(pbj.wife);

此时的pbjwife键对应的对象中,也有了gender键,且值为。当对象的属性的值是引用类型数据的时候,浅拷贝会将这个引用类型数据的地址也拷贝过来,也就是说没有完全的形成一个新对象,还是跟原对象有些关联。这就是浅拷贝。

拷贝中的值是引用类型

数组浅拷贝

Array系统构造函数原型上的concat和slice方法

concat方法
var arr = [1,2,3];
var brr = arr.concat()
arr.push(4);
console.log(arr);
console.log(brr);

此时的brr跟原来的arr是一模一样的,改变了arr后,brr也是没有发生改变的,因为brr的数据空间是一个新的地址。

数组浅拷贝concat

slice方法
var arr = [1,2,3];
var brr = arr.slice();
arr.push(4);
cosnole.log(arr);
cosnole.log(brr);

此时的brr跟原来的arr是一模一样的,改变了arr后,brr也是没有发生改变的,因为brr的数据空间是一个新的地址。

数组浅拷贝-slice

注意:如果数组中的数据有引用类型数据,上面两个方法对于数组的拷贝,会将这个引用类型数据的地址也拷贝出来。

var arr = [1,2,[3,4]];
var brr = arr.concat();
arr[2].push(5);
console.log(arr[2]);
console.log(brr[2]);

此时brr的下标2数据中,也会多出5

数组中有引用类型的浅拷贝

slice也是一样的

var arr = [1,2,[3,4]];
var brr = arr.slice();
arr[2].push(5);
console.log(arr[2]);
console.log(brr[2]);

此时brr的下标2数据中,也会多出5

数组中有引用类型的浅拷贝

这就是浅拷贝,如果数据中都是基本类型数据,就是完全没有联系的两个数据,但是如果数据中引用类型数据,那两个变量还是有一定的联系。

所谓浅拷贝,也就是说,数组或对象中的值如果是基本类型数据,那拷贝后的数据和原数据是完全没有关联,且互不影响的两个数据,如果数组或对象的值是引用类型数据的话,拷贝后的数组或对象中的引用类型的值跟原数据中的引用类型的值,还是存在共享同一地址的现象。

深拷贝

深拷贝,就是不管原数据中值是什么类型的数据,拷贝后的新数据跟原数据是完全没有关联的。

1、利用json数据和json字符串之间的转换

对象深拷贝

var obj = {
    name:"张三",
    age:12,
    wife:{
        name:"翠花",
        age:20
    }
}
var str = JSON.stringify(obj);
var pbj = JSON.parse(str);
obj.wife.gender = '女';
console.log(obj.wife);
console.log(pbj.wife);

此时pbjwife数据中没有gender键,不受obj的影响。

对象深拷贝

数组深拷贝

var arr = [1,2,[3,4]];
var str = JSON.stringify(arr);
var brr = JSON.parse(str);
arr[2].push(5);
console.log(arr[2]);
console.log(brr[2]);

此时brr下标2的数据没有5,不受arr的影响。

数组深拷贝

2、利用递归遍历对象或数组

function clone(source){
    var result;
    if(Object.prototype.toString.call(source)==='[object Object]'){
        result = {};
    }else if(Object.prototype.toString.call(source)==='[object Array]'){
        result = []
    }else{
        return;
    }
    for(var attr in source){
        if(Object.prototype.toString.call(source[attr])==='[object Array]' || Object.prototype.toString.call(source[attr])==='[object Object]'){
            result[attr] = clone(source[attr])
        }else{
            result[attr] = source[attr];
        }
    }
    return result;
}

使用:

var arr = [1,2,{
    name:"张三",
    age:12,
    wife:{
        name:"翠花",
        age:11
    }
}];
var res = clone(arr)

res[0] = 5;
console.log(arr[0],res[0]); // 1 5
res[2].name = '李四'
console.log(arr[2].name,res[2].name); // 张三 李四

调用函数得到的新数据和原来的数据互不影响。


递归深拷贝

总之,赋值是赋值,拷贝是拷贝。

浅拷贝,当对象或数组中的数据都是基本数据类型的时候,两个数据之间完全是独立的,如果对象或数组中的值是引用类型的时候,里面是引用类型的值,还是会保持共同的内存地址;

深拷贝出来的两个数据是完全独立的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • 在ES5版本的js中我们的javascript一共有6种数据类型,分别是: Number(数值型)、String...
    兮O阅读 205评论 0 0
  • 先简单说下什么是深拷贝和浅拷贝 首先我们需要了解JS的数据类型,js的数据类型分为基本数据类型(Number,St...
    前端小菜鸟阅读 138评论 0 1
  • 如何判断数组类型 typeof ❌对Array不起作用,会将结果判断为object,同理null instance...
    糕糕AA阅读 209评论 0 0
  • ---针对引用类型 传统复制 将两个变量都指向了同一块内存空间,A变动B也会随之变动; JavaScript le...
    米娅小栈阅读 243评论 0 0
  • 原网址:https://www.cnblogs.com/dengyao-blogs/p/11466598.html...
    王果果阅读 378评论 0 0