JS - 浅拷贝与深拷贝的理解以及简单实现方法
前几天撸项目代码时, 由一个技术点间接牵扯出了这东西. 所以就来总结一下.
深拷贝
拷贝对象每个层级的属性.
作用的对象是 js中引用类型的对象,基本类型没有涉及.
本质上将引用类型的对象在堆上重新开辟一块新的空间进行存放.
1 var p_1 = {name: '病猫', age: 22}; 2 var p_3 = {name: p_1.name, age: p_1.age}; 3 p_3.name = "迪迦"; 4 console.log("p_1", p_1); //p_1 {name: "子川", age: 22} 5 console.log("p_3", p_3); //p_3 {name: "迪迦", age: 22}
浅拷贝
对于引用类型的对象, 浅拷贝是在栈上重新定义了一个指针,指向的位置却依然是堆中同一对象.
1 var p_1 = {name: '病猫', age: 22}; 2 var p_2 = p_1; 3 p_2.name = "子川"; 4 console.log("p_1", p_1); //p_1 {name: "子川", age: 22} 5 console.log("p_2", p_2); //p_2 {name: "子川", age: 22}
实现方法
①: JSON的序列化与反序列化
1 let o = JSON.parse(JSON.stringify(obj)); 2 //但是obj中若含有 function, undefined, 正则表达式 时, 3 //o 中 function, undefined不存在, 正则表达式对应变成了 {};
②: 递归 (对日期和正则做了简单处理,)
1 function deepHandle(obj) { 2 let tempObj = Array.isArray(obj) ? [] : {}; 3 if (obj && typeof obj === "object") { 4 for (key in obj) { 5 if (obj.hasOwnProperty(key)) { //判断自身属性 6 if (obj[key] && typeof obj[key] === "object") { //是对象类型 7 let type = Object.prototype.toString.call(obj[key]).slice(8, -1); //具体对象类型 8 console.log("类型", type); 9 //Date 与 RegExp 不处理的话, 拷贝之后会成 {}, 10 if (type === 'Date') { 11 tempObj[key] = new Date(obj[key]); 12 } else if (type === 'RegExp') { 13 tempObj[key] = new RegExp(obj[key]); 14 } else { 15 tempObj[key] = deepHandle(obj[key]); 16 } 17 } else { 18 tempObj[key] = obj[key]; 19 } 20 } 21 } 22 } 23 return tempObj; 24 } 25 let obj = { 26 a: '于康', 27 b: { 28 age: 21, 29 city: "山西", 30 n: [1,2,3, new Date(), /234/igm] 31 }, 32 c: undefined, 33 d: null, 34 e: true, 35 f: new Date(), 36 h: {}, 37 i: /234/igm, 38 toEat: function() { 39 console.log("吃法") 40 } 41 } 42 let deepObj = deepHandle(obj); 43 let deepObj2 = JSON.parse(JSON.stringify(obj)); 44 deepObj.i = /123/igm; 45 console.log("obj", obj); 46 console.log("deepObj", deepObj); 47 console.log("deepObj2", deepObj2);
补充一下数据类型
基本数据类型 (number, string, boolean, null, undefined).
①:按值访问,即可操作保存在变量中的实际值.
②:值是不可变的,
③:名-值存储在栈内存中.
1 let name = "病猫"; 2 name = "迪迦"; 3 //看似 name 的值发生了改变, 实际改变的是 指针指向;
引用数据类型 (即对象类型Object type. 如: Object, Array, Function, Date等)
1 let obj = {name: "病猫", age: 22}
①: 堆内存中存放引用数据类型的对象 (即 {name: "病猫", age: 22})
②: 栈内存中存放引用数据类型的变量名 (即 obj) 和 此对象的 引用地址(即 指针);
③: javascript 不允许直接访问与操作堆内存空间, 只能操作对象在栈中的引用地址
结尾
以上内容是记录自己理解知识后的笔记, 若理解有误, 望您能指出. 感激不尽. 对于这个知识点,网上很多写的通俗易懂的文章(图文), 很Nice的.