现象

我们先来看一个demo

// 我们先申明一个变量str1,
// 然后把变量str1负值(拷贝)给变量str2
// 最后对变量str2进行修改操作
var str1 = 'shen'
var str2 = str1
str2 += 'zhiyong'
console.log('str1:', str1)       //shen
console.log('str2:', str2)         //shenzhiyong

我们申明一个对象并对它进行相同的操作

var obj1 = {name: 'shen'
}
var obj2 = obj1
obj2.name = 'shenzhiyong'//期望输出
// obj1: {name: "shen"}
// obj2: {name: "shenzhiyong"}console.log('obj1:', obj1)   // obj1: {name: "shenzhiyong"}
console.log('obj2:', obj2)   // obj2: {name: "shenzhiyong"}

我们不难发现结果并不是我们预期的那样, 这是为什么呢?如果将obj1改成数组对象进行操作,亦是同样的结果。

原因:由于String类型属于基本数据类型,Object(Array)属于引用数据类型。当我们申明一个基本类型并对它进行赋值的时候,计算机会将值保存在栈内存中。而当我们申明一个引用数据类型并对它进行赋值的时候,计算机会将值保存在堆内存中,引用类型变量其实就是一个指针指向堆内存中。如果复制两相同的引用类型变量,其实它们最终指向同一个对象或者说堆内存空间。

关于JavaScript的数据类型 我们先埋下一个坑!

一、浅拷贝

对象和数组的浅拷贝代码如下:

var obj1 = {name: 'shen'
}
var obj2 = obj1
obj2.name = 'shenzhiyong'console.log('obj1:', obj1)   // obj1: {name: "shenzhiyong"}
console.log('obj2:', obj2)   // obj2: {name: "shenzhiyong"}var arr1 = [1,2,3]
var arr2 = arr1
arr2.push(4)
console.log('arr1:', arr1)   // arr1: [1,2,3,4]
console.log('arr2:', arr2)   // arr2: [1,2,3,4]

浅拷贝的意思就是只复制引用,没有复制真正的值。有时候我们只是想保留对象的数据,单纯想改变obj2和arr2的值,但是原对象的数据也发生了改变。很多时候这种情况都不是我们想要的。为了解决这个问题: 深拷贝它来了!

二、深拷贝

JSON方法

var obj1 = {name: 'shen'
}
var obj2 = JSON.parse(JSON.stringify(obj1))
obj2.name = 'shenzhiyong'console.log('obj1:', obj1)   // obj1: {name: "shen"}
console.log('obj2:', obj2)   // obj2: {name: "shenzhiyong"}

优点:简单明了,方便记忆

缺点:看下面代码。当对象里面出现函数的时候就不适用了。

var obj1 = {name: 'shen',show: function (argument) {console.log(1)}
}
var obj2 = JSON.parse(JSON.stringify(obj1))
console.log('obj1:', obj1)  // obj1: {name: "shen", show: ƒ}
console.log('obj2:', obj2)  // obj2: {name: "shen"}

手写递归方法

function deepCopy(obj) {var newobj = obj.constructor === Array ? [] : {};if (typeof obj !== 'object') {return obj;} else {for (var i in obj) {if (typeof obj[i] === 'object'){ //判断对象的这条属性是否为对象newobj[i] = deepCopy(obj[i]);  //若是对象进行嵌套调用}else{newobj[i] = obj[i];}}}return newobj; //返回深度克隆后的对象
}var obj1 = {name: 'shen',show: function (argument) {console.log(1)}
}
var obj2 = deepCopy(obj1)
console.log('obj1:', obj1)  // obj1: {name: "shen", show: ƒ}
console.log('obj2:', obj2)  // obj2: {name: "shen"}

优点:能够实现对象和数组的深拷贝

缺点:如果拷贝的对象嵌套过深的话,会对性能有一定的消耗

第三方库 jQuery.extend 和 lodash

$.extend( true, object1, object2 ); // 深度拷贝
$.extend( object1, object2 );  // 浅拷贝var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]); // => false

大佬写的东西,我只能说:逃

三、重点来了:具有局限性的深拷贝(有些面试官就喜欢问这个地方的东西)

当对象或者数组内部的都是基本数据类型的话,以下的方式可以实现深拷贝。但是如果出现了引用类型嵌套引用类型的话。以下方法将不可用。

看下面代码:

var obj = {name: 'shen'
}var obj2 = {innner: {name: 'shen'}
}

以下方法仅支持obj此类对象的深度拷贝不支持obj2此类对象

es6解析结构 「...」

var obj1 = {name: 'shen',show: function (argument) {console.log(1)}
}
var obj2 = { ...obj1 }
obj2.name = 'shenzhiyong'
console.log('obj1:', obj1)  // obj {name: "szy", show: ƒ}
console.log('obj2:', obj2)   // obj2 {name: "shenzhiyong", show: ƒ}

Object.assign()

var obj1 = {name: 'shen',show: function (argument) {console.log(1)}
}
var obj2 = Object.assign(obj1)
obj2.name = 'shenzhiyong'
console.log('obj1:', obj1)  // obj {name: "szy", show: ƒ}
console.log('obj2:', obj2)   // obj2 {name: "shenzhiyong", show: ƒ}

数组中的slice() & concat()

var arr1 = [1,2,3]
var arr2 = arr1.slice()  // 方法一
// var arr2 = arr1.concat()  //方法二
arr2.push(4)
console.log('arr1:', arr1)  // arr1: [1, 2, 3]
console.log('arr2:', arr2)  // arr1: [1, 2, 3, 4]

总结:要想实现真正意义的深拷贝,个人觉得还是递归的方法比较靠谱。其实看第三方的库也是采用这样的做法。在实际的生产当中,我使用的是lodash。

放水完毕!

vue对象深拷贝_JS 对象的深拷贝和浅拷贝相关推荐

  1. python怎样给对象赋值_Python对象赋值、浅拷贝和深拷贝

    总结: 1.copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象 2.copy.deepcopy 深拷贝 拷贝对象及其子对象 1.对象赋值 will = ["Will&quo ...

  2. python中一切数据都是对象吗_python中的深拷贝(deepcopy)和浅拷贝(copy)

    前言 在很多语言中都存在深浅拷贝两种拷贝数据的方式,Python中也不例外.本文中详细介绍了Python中的深浅拷贝的相关知识,文章的内容包含: 对象.数据类型.引用 赋值 浅拷贝 深拷贝 一.Pyt ...

  3. js 对象深拷贝、对象数组深拷贝的几种方法总结

    写前端的时候经常会遇到对象的拷贝,一般我们会用到深拷贝,深拷贝就是完完整整的将一个对象从内存中拷贝一份出来,放到另一块新开辟的内存中去.向下面这种赋值是浅拷贝,a.b都是对同一块内存进行引用,a.b哪 ...

  4. vue 对象继承_JS面向对象—对象的继承

    面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过"类&qu ...

  5. vue 深度拷贝数组_前端深拷贝和浅拷贝

    在前端攻城狮的工作实际应用中,有很多情况下在处理数据的时候,会用到数据的深拷贝和浅拷贝 例如:vue中数据是双向绑定的,页面显示依赖于从后台获取到的数据,但要将这个数据当做参数发送给另外一个接口的时候 ...

  6. js 浅拷贝直接赋值_JS中的赋值、浅拷贝与深拷贝

    作者:奚杰 拷贝是写代码中经常使用的方法.浅拷贝与深拷贝是指拷贝的两种情况.本文将深入探究JS的赋值.浅拷贝与深拷贝. 数据类型 在探究深拷贝与浅拷贝之前,我们先梳理一下JS的数据类型.在JavaSc ...

  7. ES6 深拷贝_JS基本数据类型和引用数据类型的区别及深浅拷贝

    1.栈(stack)和堆(heap) stack为自动分配的内存空间,它由系统自动释放:而heap则是动态分配的内存,大小也不一定会自动释放 2.数据类型 JS分两种数据类型: 基本数据类型:Numb ...

  8. vue更新数组和对象

    vue更新数组和对象 https://cn.vuejs.org/v2/guide/list.html#数组更新检测 更改数组对象 let items=this.formValidate.items; ...

  9. vue中的props对象

    vue中的props对象 1.props对象的定义 props其实是properties的缩写,props对象是用来定义属性的.props对象可以接受数组形式的参数又或者是对象形式的参数. 数组形式 ...

最新文章

  1. Firefox 插件:鲜味 del.icio.us,和朋友分享你的收藏
  2. 第五周课程总结试验报告(三)
  3. python安装第三方库
  4. 使用ffmpeg合并视频文件的三种方法
  5. 将社交登录添加到Spring MVC Web应用程序:配置
  6. luogu P1427 小鱼的数字游戏
  7. 【Python3网络爬虫开发实战】 1.7.1-Charles的安装
  8. python在什么平台开发_python主要用于开发什么
  9. java sql 写入万条数据_如何快速向数据库插1000万数据?4种方法对比,它简单却速度最快
  10. 关于学习新知识的一点想法
  11. 浏览器宽度和高度的说明
  12. win下编译TNN安卓库(静态或者动态) + android studio ndk调用
  13. win10用win7的图片查看器
  14. 人生无常,心安便是归处
  15. BT-3の蓝牙技术原理のBT协议の蓝牙核心协议の链路管理协议(LMP)
  16. 数学到底有多重要呢?
  17. iOS事件传递链与响应链
  18. 关于unityHDRP RenderTexture透明通道搜集资料
  19. 笔记本插网线无法联网解决方法
  20. java as关键字_Java 关键字专题

热门文章

  1. pytorch中调整学习率: torch.optim.lr_scheduler
  2. 51nod1380 夹克老爷的逢三抽一
  3. Eclipse 使用 SVN 插件后修改用户方法汇总
  4. JSON C# Class Generator ---由json字符串生成C#实体类的工具(转)
  5. Wayland 1.0 发布,图形服务器
  6. FLEX教程:改变LIST控件项被选中的背景提示效果.
  7. 22款Android App传藏后门用广告耗手机电量
  8. 顺藤摸瓜的解决GDB的DEBUG中出现的小问题
  9. 读《世界是数字的》笔记
  10. 比特币网站Flexcoin遭黑客攻击 损失极大 被迫关闭