深浅拷贝的方法

堆栈理解

基本数据类型 number、string、boolean、null、undefined
引用数据类型 object、function、array
栈内存 存储基本数据类型内容(值之间的比较)
堆内存 存储复杂数据类型内容(地址之间的比较)

深浅拷贝理解

对于基本数据来说没有深浅拷贝的这一说法、因为基本数据都是存在栈内存中的,直接是直接拷贝值就可以了,所有的深浅拷贝都是基于复杂数据类型来说的。

浅拷贝理解:

  1. 复杂数据类型:就是进行内存地址的传递、两个引用指向了同一个内存地址、并未开辟新的内存空间存放拷贝后的对象、所以当我们修改拷贝后的值的时候,源数据还是会被影响更改
  2. 对象:只会拷贝对象的第一层、嵌套的复杂数据类型依旧和原对象这个属性指向相同的地址。

深拷贝理解:

  1. 复杂数据类型:深拷贝就是完完全全拷贝的一份新的对象、它会再内存中的堆区域重新开辟空间、修改拷贝后的对象是不会影响到源对象。
  2. 对象:将整个对象都拷贝过来、嵌套的复杂数据类型和源对象这个属性都指向不同的地址。

对象:当中的深浅拷贝

1、JSON.parse(JSON.stringify(待拷贝对象))深拷贝

  • 可以实现多层拷贝(就是再对象里面还有对象也会拷贝)
  • 缺点:无法拷贝一些数据(由于是使用的json的序列化,所以当json里面没有的方法和数据格式,那就无法进行拷贝)
    • undefined不会被拷贝
    • function不会被拷贝
    • Symbol类型不会被拷贝
  • 缺点二:
    • NaN、Infinity、-Infinity等数据都会被拷贝成null
let person = {test:null, //会被拷贝test1:undefined,  //不会被拷贝sym:Symbol('zrs'),num1:NaN,num2:Infinity,num3:-Infinity,name: 'rose',age: 18,son: { //第二层对象name: 'rose_son'},like() { //第二层函数console.log('喜欢唱歌、滑冰');}
}// 使用深拷贝方法
let new_person = JSON.parse(JSON.stringify(person))
// 更改拷贝后的值
new_person.age = 20
new_person.name = 'new_rose'
new_person.son.name = 'new_rose_son'
// 打印新老数据比对
console.log(person);
console.log(new_person);

2.使用展开运算符实现对象的浅拷贝=

  • 使用展开运算符,对象的第一层可以被拷贝、但是深层的数据不可以被拷贝。
let person = {name: 'rose',
age: 18,
son: { //第二层对象
name: 'rose_son'
},
like() { //第二层函数
console.log('喜欢唱歌、滑冰');
}
}// 使用深拷贝方法
let new_person = {...person}
// 更改拷贝后的值
new_person.age = 20
new_person.name = 'new_rose'
new_person.son.name = 'new_rose_son'
// 打印新老数据比对
console.log(person);
console.log(new_person);

3.使用递归函数来实现深拷贝

  • 是我个人最喜欢用的方法,没有任何的限制
let person = {test:null, test1:undefined,  sym:Symbol('zrs'), num1:NaN,num2:Infinity,num3:-Infinity,name: 'rose',age: 18,son: { //第二层对象name: 'rose_son'},like() { //第二层函数console.log('喜欢唱歌、滑冰');}
}// 实现深拷贝的函数
const cloneData = data => {// 根据传入的数据类型,创建新的数据是简单对象还是数组const newData = Array.isArray(data) ? [] : {}// 遍历传入的数据for (let key in data) {// 属性存在,且为对象,那么直接递归一下if (data[key] && typeof data[key] === 'object') {newData[key] = cloneData(data[key]) // 递归} else {newData[key] = data[key]}}return newData
}// 使用深拷贝方法
let new_person = cloneData(person)// 更改拷贝后的值
new_person.age = 20
new_person.name = 'new_rose'
new_person.son.name = 'new_rose_son'
// 打印新老数据比对
console.log(person);
console.log(new_person);

数组:当中的深浅拷贝

slice浅拷贝

  1. 当数据为基本数据时、可以实现基本数据的深拷贝
  2. 但是数据威引用数据类型时、为浅拷贝
/* 基本数据类型的拷贝可实现 */
let arr1 = [0,1,3,5,9]
let arr2 = arr1.slice()
arr2[0] = 88
console.log(arr1); //[0, 1, 3, 5, 9]
console.log(arr2); //[88, 1, 3, 5, 9]/* 引用数据类的的数组 */
//无法实现引用对象的拷贝
let arr3 = [{name:'zjf',age:23},{name:'rose',age:20}]
let arr4 = arr3.slice()
arr4[0].name = 'jack'
console.log(arr3);//{name:'jack',age:23},{name:'rose',age:20}
console.log(arr4);//{name:'jack',age:23},{name:'rose',age:20}

concat浅拷贝

  • concat这个方法可以连接两个数组。
  • 当数组数据为基本数据时、可以实现(某种意义的)深拷贝
  • 当数组数据为引用数据时、为浅拷贝
/* 基本数据类型的拷贝可实现 */
let arr1 = [0,1,3,5,9]
let arr2 = [].concat(arr1)
arr2[0] = 88
console.log(arr1); //[0, 1, 3, 5, 9]
console.log(arr2); //[88, 1, 3, 5, 9]/* 引用数据类的的数组 */
//无法实现引用对象的拷贝
let arr3 = [{name:'zjf',age:23},{name:'rose',age:20}]
let arr4 = [].concat(arr3)
arr4[0].name = 'jack'
console.log(arr3);//{name:'jack',age:23},{name:'rose',age:20}
console.log(arr4);//{name:'jack',age:23},{name:'rose',age:20}

…展开运算符浅拷贝

  • 当数组数据为基本数据时、可以实现(某种意义的)深拷贝
  • 当数组数据为引用数据时、为浅拷贝
/* 基本数据类型的拷贝可实现 */
let arr1 = [0,1,3,5,9]
let arr2 = [...arr1]
arr2[0] = 88
console.log(arr1); //[0, 1, 3, 5, 9]
console.log(arr2); //[88, 1, 3, 5, 9]/* 引用数据类的的数组 */
//无法实现引用对象的拷贝
let arr3 = [{name:'zjf',age:23},{name:'rose',age:20}]
let arr4 = [...arr3]
arr4[0].name = 'jack'
console.log(arr3);//{name:'jack',age:23},{name:'rose',age:20}
console.log(arr4);//{name:'jack',age:23},{name:'rose',age:20}

JSON.parse(JSON.stringify(arr1))深拷贝

  • 可实现对数组里面的引用对象进行深拷贝
  • 缺点跟对象里面的一样
/* 基本数据类型的拷贝可实现 */
let arr1 = [0,1,3,5,9]
let arr2 = JSON.parse(JSON.stringify(arr1))
arr2[0] = 88
console.log(arr1); //[0, 1, 3, 5, 9]
console.log(arr2); //[88, 1, 3, 5, 9]/* 引用数据类的的数组 */
//无法实现引用对象的拷贝
let arr3 = [{name:'zjf',age:23},{name:'rose',age:20}]
let arr4 = JSON.parse(JSON.stringify(arr3))
arr4[0].name = 'jack'
console.log(arr3);//{name:'zjf',age:23},{name:'rose',age:20}
console.log(arr4);//{name:'jack',age:23},{name:'rose',age:20}

递归函数实现深拷贝

// 实现深拷贝的函数
const cloneData = data => {// 根据传入的数据类型,创建新的数据是简单对象还是数组
const newData = Array.isArray(data) ? [] : {}
// 遍历传入的数据
for (let key in data) {// 属性存在,且为对象,那么直接递归一下
if (data[key] && typeof data[key] === 'object') {newData[key] = cloneData(data[key]) // 递归
} else {newData[key] = data[key]
}
}
return newData
}/* 基本数据类型的拷贝可实现 */
let arr1 = [0, 1, 3, 5, 9]
let arr2 = cloneData(arr1)
arr2[0] = 88
console.log(arr1); //[0, 1, 3, 5, 9]
console.log(arr2); //[88, 1, 3, 5, 9]/* 引用数据类的的数组 */
//无法实现引用对象的拷贝
let arr3 = [{name: 'zjf',
age: 23,
son:{name:'zjf_son'
}
}, {name: 'rose',
age: 20
}]
let arr4 = cloneData(arr3)
arr4[0].name = 'jack'
arr4[0].son.name = 'jack_son'
console.log(arr3); //{name:'zjf',age:23},{name:'rose',age:20}
console.log(arr4); //{name:'jack',age:23},{name:'rose',age:20}

js中深浅拷贝理解与方法相关推荐

  1. JS中深浅拷贝 函数封装代码

    一.了解 基本数据类型保存在栈内存中,按值访问,引用数据类型保存在堆内存中,按址访问. 二.浅拷贝 浅拷贝只是复制了指向某个对象的指针,而不是复制对象本身,新旧对象其实是同一内存地址的数据,修改其中一 ...

  2. php深浅拷贝,js实现深浅拷贝方法

    说起深浅拷贝,我觉得需要理清楚 值类型 和 引用类型,本文主要和大家分享js实现深浅拷贝方法,希望能帮助到大家. 值类型 所谓 值类型 就是 undefined,null,number, string ...

  3. JS中setter/getter理解

    JS中setter/getter理解 JS对象属性 get/set和getter/setter 数据属性 Object.defineProperty() 访问器属性 getter/setter创建及删 ...

  4. js中给数组添加元素的方法有哪些

    js中给数组添加元素的方法有哪些 unshift:将参数添加到原数组开头,并返回数组的长度 pop:删除原数组最后一项,并返回删除元素的值:如果数组为空则返回undefined push:将参数添加到 ...

  5. js中取得变量绝对值的方法

    本文实例讲述了js中取得变量绝对值的方法.分享给大家供大家参考.具体分析如下: 绝对值在js中我们直接使用abs函数来求,这里就来整理一些关于js中取得变量的绝对值的方法,以便让大家更深入的理解js绝 ...

  6. js中修改this的指向方法整理

    JavaScript(简称"JS") 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言.虽然它是作为开发Web页面的脚本语言而出名,但是它也被用到了很多非浏览器环境中,Ja ...

  7. JavaScript -- 时光流逝(三):js中的 String 对象的方法

    JavaScript -- 知识点回顾篇(三):js中的 String 对象的方法 (1) anchor(): 创建 HTML 锚. <script type="text/javasc ...

  8. JS中的call()和apply()方法(转)

    转自:http://uule.iteye.com/blog/1158829 JS中的call()和apply()方法 博客分类: JS 1.方法定义 call方法:  语法:call([thisObj ...

  9. js中改变原数组的方法以及解决改变原数组的方法

    js中改变原数组的方法以及解决改变原数组的方法 参考文章: (1)js中改变原数组的方法以及解决改变原数组的方法 (2)https://www.cnblogs.com/Ingots/p/1151701 ...

最新文章

  1. 以下一些使用ASP.NET和VISUAL STUDIO.NET2003的经验和技巧
  2. 001_python单元测试
  3. 无法创建 SSIS 运行时对象。请验证 DTS.dll 是否可用及是否已注册。此向导无法继续而将终止。 (SQL
  4. 基于GRU和am-softmax的句子相似度模型 | 附代码实现
  5. UE4学习-材质快捷键及材质帮助手册
  6. 布法罗博士计算机专业回国人员,四名UW学生参加爱达荷州国家实验室的实习计划...
  7. 大学生计算机python_非计算机专业的大学生,想学习Python需要多长时间
  8. 佛系程序员:什么bug不bug的,随缘吧
  9. ElasticSearch中的分析器是什么?
  10. mysql 单精度和双经度,mysql – 计算距离给定2点,纬度和经度
  11. 【kmp专题】牛客网子串(进制转化+kmp/string.find())
  12. 20190801H3C无线控制器3510H 版本升级总结
  13. IE新功能:十大特色IE插件(转)
  14. 免费云服务器(阿贝云服务器入门)(仅适用于windows server系统)
  15. 游戏引擎平面折线和直线路径跟随算法
  16. EBS 12.1.3 应用打补丁操作及问题处理
  17. 面试官最容易提出的20个问题
  18. 产品和运营区别是什么,别迷惑了。
  19. 国耀明医院互联网医院:儿童医保门诊不报销???你错啦!
  20. Python|泰坦尼克号幸存者画像

热门文章

  1. Idea运行单元测试 Test framework quit unexpectedly
  2. freecodecamp_freeCodeCamp发布样式指南
  3. HDMI接口类型种类区分图(高清图)
  4. 极端行情下,如何通过期权做好风险管理? | TI对话首席
  5. MUR20060CT-ASEMI快恢复模块MUR20060CT
  6. 奥比中光-Astra相机如何用python实现输出RGB彩色图和Depth深度图,并输出三维坐标代码
  7. 奥比中光 ORBBEC Astra Mini Pro简单使用
  8. Honest Coach
  9. DB2使用db2advis工具调优SQL
  10. Android:收不到应用卸载、替换、安装等广播