讲到前端中的深拷贝与浅拷贝之前需要先简单了解下js中的堆与栈:
1、堆和栈都是运行时内存分配的一个数据区
2、js的变量类型有哪些
3、浅拷贝和深拷贝
4、有属性对象的对象不能用ES6提供的Object.assign()以及扩展运算符(...)
5、有属性对象的对象怎么深拷贝
6、多维数组如何深拷贝
(1)堆(heap)
堆(heap)用于复杂数据类型(引用类型)分配空间,例如数组对象、object对象;
它是运行时动态分配内存的,因此存取速度较慢
(2)栈(stack)
栈(stack)中主要存放一些(基本类型)的变量和对象的引用,(包含池、池存放常量),
其优势是存取速度比堆要快,并且栈内的数据可以共享,但缺点是存在栈中的数据大小
与生存期必须是确定的,缺乏灵活性
(1)值类型(基本类型):字符串(string)、数值(number)、布尔值(boolean)、undefined、null、symbol(这6种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值)(ECMAScript 2016新增了一种基本数据类型:symbol)
值类型复制时复制的是值本身
保存在栈中,占用空间固定,随着方法运行结束,方法内定义的变量会随之销毁
使用typeof检测数据类型
(2)引用类型:对象(Object)、数组(Array)、函数(Function)、包括有正则表达式
引用类型复制时复制的是指向对象的一个指针
使用 instanceof 检测数据类型
使用new()方法构造出的对象是引用型
(1)浅拷贝:对地址的引用,只要我们修改了一个拷贝后的(数组、对象等),那么原(数组、对象等)也会改变。
var obj = {
name:"前端",
age:"10"
}
var oldObj = obj;
obj.name = "html + css + js";
console.log(oldObj); //{name: "html + css + js", age: "10"}
(2)深拷贝:属于创建了一个新的内存空间。 他们不在会共用同一个内存空间。是两个完全独立的对象或数组。
var obj = {
name:"前端",
age:"10"
}
var oldObj = {...obj};
obj.name = "html + css + js";
console.log(oldObj); //{name: "前端", age: "10"}
SE6提供的深拷贝的方法Object.assign()以及扩展运算符(...); (前提是没有属性对象)
如:若被拷贝的对象中有属性对象,则依然会影响到被拷贝对象。
var obj = {
smallObj:{name:"obj",
age:"10"
},
name:"前端",
age:"10"
}
var oldObj = {...obj};
oldObj.smallObj.name = "html + css + js";
console.log(obj);
打印为:
用扩展运算符对数组或者对象进行拷贝时,只能扩展和深拷贝第一层的值,对于第二层极其以后的值,扩展运算符将不能对其进行打散扩展,也不能对其进行深拷贝,即拷贝后和拷贝前第二层中的对象或者数组仍然引用的是同一个地址,其中一方改变,另一方也跟着改变。
封装的方法:
function deepClone(obj) {
var newObj = Array.isArray(obj) === true ? [] : {};
for (let key in obj) {
if (typeof obj[key] == 'object') {
newObj[key] = deepClone(obj[key]);
} else {
newObj[key] = obj[key];
}
}
return newObj;
}
var formItem = {
version:"版本号",
corporationBasicInfo:{
"corporationName":"法人姓名",
"corporationIdCardType":"法人证件类型",
"corporationIdCardNo":"法人证件号码",
}
}
let b = deepClone(formItem);
对象b的打印:
改变对象 b 中的某个属性对象的属性值
b.corporationBasicInfo.corporationIdCardNo = 1
console.log(b)
对象 b 的打印:
console.log(formItem)
被拷贝对象 formItem 的打印:
或者利用json数据和json字符串之间的转换
var formItem = {
version:"版本号",
corporationBasicInfo:{
"corporationName":"法人姓名",
"corporationIdCardType":"法人证件类型",
"corporationIdCardNo":"法人证件号码"
}
}
var str = JSON.stringify(formItem);
var pbj = JSON.parse(str);
formItem.corporationBasicInfo.corporationIdCardNo=1;
console.log(formItem);
console.log(pbj);
打印为:
function deepcopy(obj) {
var out = [];
for (let i=0; i < obj.length; i++) {
if (obj[i] instanceof Array){
out[i] = deepcopy(obj[i]);
}else{
out[i] = obj[i];
}
}
return out;
}
let a = [1, 2, 3, 4, 5, 6, [1, 2, 3]];
let b = deepcopy(a);
b[6][0] = 100
console.log(b);
console.log(a);
打印为: