JavaScript对象存在两种类型。一种是基本类型,另一种是引用类型。
基本类型存放在栈内存,引用类型存放在堆内存。堆内存用于存放由new创建的对象,栈内存存放一些基本类型的变量和对象的引用变量。
基本数据类型(number,string,undefined,null,boolean),这是js中的5种基本数据类型。这些类型的值存放在栈内存中(string类型的实际值是存放在堆内存中的,但是js把string当作基本数据类型来处理)。
1. js中的浅复制和深复制
浅复制和深复制都可以在已有对象的基础上再生一份实例。复制的时候存在两种情况:复制引用和复制实例。
第一种:浅复制
浅复制是复制引用,复制后,两个对象指向同一空间,如果其中一个发生改变,另一个也会发生改变。
var src = {
name:"src"
};
var target = src;
console.log(src.name);
console.log(target.name);
target.name = "target";
console.log(src.name);
console.log(target.name);
代码运行结果:
浅复制仅仅是指向被复制的内存地址,如果改变其中一个,另一个也会发生变化。
第二种:深复制
深复制是复制实例,是在计算机中开辟了一块内存地址来存放复制的对象。
(1). 通过JSON对象的stringify和parse可以实现对象的深复制。
stringify方法可以将js对象序列化为字符串;
parse方法可以将字符串反序列化为js对象。
var src = {
name:"src",
child:{
name:"src-child"
}
};
var target = src; //浅复制
console.log(src.name + "," + src.child.name);
console.log(target.name + "," + target.child.name);
var obj = JSON.parse(JSON.stringify(src)); //深复制
console.log(src.name + "," + src.child.name);
console.log(obj.name + "," + obj.child.name);
obj.name = "obj";
obj.child.name = "obj-child";
console.log(src.name + "," + src.child.name);
console.log(obj.name +"," + obj.child.name);
代码运行结果:
这种方法的缺点是:只有可以转换为JSON格式的对象才可以这样用。
例如:function无法转换为JSON格式,则不能采用这种方法实现深复制。
(2). 递归拷贝
function deepClone(initialObj,finalObj){
var obj = finalObj || {};
for(var i in initialObj){
if(typeof initialObj[i] === "object"){
obj[i] = (initialObj[i].constructor === Array)?[]:{};
deepClone(initialObj[i],finalObj[i]);
}
else{
obj[i] = initialObj[i];
}
}
return obj;
}
深复制与浅复制的根本区别在于:是否真正获取了一个对象的复制实体,而不是引用。
深复制在计算机中开辟了一块内存地址用于存放复制的对象;
浅复制仅仅是指向被复制的内存地址,改变其中一个,另一个也会发生变化。