JS - 浅拷贝与深拷贝的理解以及简单实现方法
前几天撸项目代码时, 由一个技术点间接牵扯出了这东西. 所以就来总结一下.
深拷贝
拷贝对象每个层级的属性.
作用的对象是 js中引用类型的对象,基本类型没有涉及.
本质上将引用类型的对象在堆上重新开辟一块新的空间进行存放.
var p_1 = {name: '病猫', age: 22};
var p_3 = {name: p_1.name, age: p_1.age};
p_3.name = "迪迦";
console.log("p_1", p_1); //p_1 {name: "子川", age: 22}
console.log("p_3", p_3); //p_3 {name: "迪迦", age: 22}
浅拷贝
对于引用类型的对象, 浅拷贝是在栈上重新定义了一个指针,指向的位置却依然是堆中同一对象.
var p_1 = {name: '病猫', age: 22};
var p_2 = p_1;
p_2.name = "子川";
console.log("p_1", p_1); //p_1 {name: "子川", age: 22}
console.log("p_2", p_2); //p_2 {name: "子川", age: 22}
实现方法
①: JSON的序列化与反序列化
let o = JSON.parse(JSON.stringify(obj));
//但是obj中若含有 function, undefined, 正则表达式 时,
//o 中 function, undefined不存在, 正则表达式对应变成了 {};
②: 递归 (对日期和正则做了简单处理,)
function deepHandle(obj) {
let tempObj = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj.hasOwnProperty(key)) { //判断自身属性
if (obj[key] && typeof obj[key] === "object") { //是对象类型
let type = Object.prototype.toString.call(obj[key]).slice(8, -1); //具体对象类型
console.log("类型", type);
//Date 与 RegExp 不处理的话, 拷贝之后会成 {},
if (type === 'Date') {
tempObj[key] = new Date(obj[key]);
} else if (type === 'RegExp') {
tempObj[key] = new RegExp(obj[key]);
} else {
tempObj[key] = deepHandle(obj[key]);
}
} else {
tempObj[key] = obj[key];
}
}
}
}
return tempObj;
}
let obj = {
a: '于康',
b: {
age: 21,
city: "山西",
n: [1,2,3, new Date(), /234/igm]
},
c: undefined,
d: null,
e: true,
f: new Date(),
h: {},
i: /234/igm,
toEat: function() {
console.log("吃法")
}
}
let deepObj = deepHandle(obj);
let deepObj2 = JSON.parse(JSON.stringify(obj));
deepObj.i = /123/igm;
console.log("obj", obj);
console.log("deepObj", deepObj);
console.log("deepObj2", deepObj2);
补充一下数据类型
基本数据类型 (number, string, boolean, null, undefined).
①:按值访问,即可操作保存在变量中的实际值.
②:值是不可变的,
③:名-值存储在栈内存中.
let name = "病猫"; name = "迪迦"; //看似 name 的值发生了改变, 实际改变的是 指针指向;
引用数据类型 (即对象类型Object type. 如: Object, Array, Function, Date等)
let obj = {name: "病猫", age: 22}
①: 堆内存中存放引用数据类型的对象 (即 {name: "病猫", age: 22})
②: 栈内存中存放引用数据类型的变量名 (即 obj) 和 此对象的 引用地址(即 指针);
③: javascript 不允许直接访问与操作堆内存空间, 只能操作对象在栈中的引用地址
结尾
以上内容是记录自己理解知识后的笔记, 若理解有误, 望您能指出. 感激不尽. 对于这个知识点,网上很多写的通俗易懂的文章(图文), 很Nice的.
JS - 浅拷贝与深拷贝的理解以及简单实现方法的更多相关文章
- 关于js浅拷贝与深拷贝的理解
前端开发中,一般情况下,很少会去在意深拷贝与浅拷贝的关系. 大家知道,js变量有2种数据类型:基本类型和引用类型.基本类型的拷贝是将整个值完全拷贝一份的,也就是深拷贝.就是开辟了新的堆内存.所以基本类 ...
- 理解js浅拷贝和深拷贝
理解深拷贝和浅拷贝之前先了解下js中的基本类型和引用类型 1.基本类型: 在js中,数据的基本类型undefined,null,string,number,boolean,在变量中赋的实际值,基本类型 ...
- 关于JS浅拷贝和深拷贝
在 JS 中有一些基本类型像是Number.String.Boolean,而对象就是像这样的东西{ name: 'Larry', skill: 'Node.js' },对象跟基本类型最大的不同就在于他 ...
- Java 浅拷贝和深拷贝的理解和实现方式
Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去.举例说明:比如,对象A和对象B都属于类S,具有属性a和b.那么对对象A进行拷贝 ...
- 【转】Java 浅拷贝和深拷贝的理解和实现方式
Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去.举例说明:比如,对象A和对象B都属于类S,具有属性a和b.那么对对象A进行拷贝 ...
- c#中浅拷贝和深拷贝的理解
c#中拷贝有浅拷贝和深拷贝之分. 例如对象A,其中有值类型字段和引用类型字段: 1.浅拷贝: 对于值类型字段,直接逐位复制到新拷贝的副本对象中,修改副本的字段的值,不会影响源对象中字段的值: 对于引用 ...
- 浅谈Javascript 浅拷贝和深拷贝的理解
javascript中存储对象都是存地址的. 浅拷贝:浅拷贝是都指向同一块内存区块,浅拷贝共用同一内存地址,你改值我也变.如果拷贝的对象里面的值是一个对象或者数组,它就是浅拷贝,拷贝的知识引用地址. ...
- js 浅拷贝和深拷贝
传值与传址 了解了基本数据类型与引用类型的区别之后,我们就应该能明白传值与传址的区别了.在我们进行赋值操作的时候,基本数据类型的赋值(=)是在内存中新开辟一段栈内存,然后再把再将值赋值到新的栈中.例如 ...
- 前端【JS】,深拷贝与浅拷贝的区别及详解!
我是前端小白一枚,为了巩固知识和增强记忆,开始整理相关的知识,方便以后复习和面试的时候看看.OK,让我们进入正题~ 先说说浅拷贝和深拷贝的理解吧,个人是这样理解的:两个对象A.B, A有数据B为空,B ...
随机推荐
- 前端异步编程之Promise和async的用法
传统的异步解决方案采用回调函数和事件监听的方式,而这里主要记录两种异步编程的新方案: ES6的新语法Promise ES2017引入的async函数 Generator函数(略) Promise的含义 ...
- 原生js实现form表单序列化
当我们有form表单而且里面的表单元素较多时,咱们总不能一个个去获取表单元素内的值来进行拼接吧!这样会很让人蛋疼!为了方便与后台交互并且提高自己的开发效率,并且不让你蛋疼:我们一起用原生来写一个表单序 ...
- 实现el-dialog的拖拽,全屏,缩小功能
基于el-dialog, 封装了一下.,实在懒得写,所以直接把代码 粘出来了 大概粘了一下效果.自己体会把. 组件使用 <el-dialog v-dialogDrag ref="xhz ...
- [剑指offer] 50. 第一个只出现一次的字符 + map,hashmap 及其区别
class Solution { public: int FirstNotRepeatingChar(string str) { map<char,int>mp; ;i<str.si ...
- BA-ALC控制模块
- POJ 1944
明天补上... 这道题的思路确实很精致.考虑到连的边肯定不会是一个环,所以至少有一个断点.于是,可以枚举这个断点.断点一确定,那么连边的走向也就确定了.用D[i]表示由i开始可以到达的最远点即可.对于 ...
- 网络抓包工具 Fiddler
网络抓包工具 Fiddler 下载网址 http://www.telerik.com/fiddler 简单介绍 Fiddler是一个http协议调试代理工具,它能够记录并检查全部你的电脑和互联网之间的 ...
- Android自己定义控件皮肤
Android自己定义控件皮肤 对于Android的自带控件,其外观仅仅能说中规中矩,而我们平时所示Android应用中,一个简单的button都做得十分美观.甚至于很多button在按下时的外观都有 ...
- web后台知识点整理
五.JEE 适用于创建server端的大型的软件服务系统 1. JEE : JAVA PLATFORM ENTERPRISE DEDITON 2.是一个规范集.技术集.框架集(API集) 一种技 ...
- 0x25 广度优先搜索
今天莫名不想说话. 结果发现效率挺高? poj3322 本来可以1a的..发现我宽搜写的是head<=tail而且初始是head=1,tail=2如果是多组数据简直就gg了.基础不牢固 这题虽然 ...