数据分为根本数据类型 (String, Number, Boolean, Null, Undefined,Symbol) 和对象数据类型。
- 根本数据类型的特点:间接存储在栈 (stack) 中的数据
- 援用数据类型的特点:存储的是该对象在栈中援用,实在的数据寄存在堆内存里
援用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找援用值时,会首先检索其在栈中的地址,获得地址后从堆中取得实体。
深拷贝和浅拷贝是只针对 Object 和 Array 这样的援用数据类型的 。最基本的区别在于是否真正获取一个 对象的复制实体,而不是援用。
假如 B 复制了 A,批改 A 的时候,看 B 是否发生变化:
如果 B 跟着 也变了,阐明是浅拷贝,拿人手短!(批改堆内存中的同一个值)
如果 B 没有扭转,阐明是深拷贝,自食其力!(批改堆内存中的不同的值)
浅拷贝(shallowCopy)只是减少了一个指针指向已存在的内存地址,
深拷贝(deepCopy)是减少了一个指针并且申请了一个新的内存,使这个减少的指针指向这个新的内存,
应用深拷贝的状况下,开释内存的时候不会因为呈现浅拷贝时开释同一个内存的谬误。
浅复制:仅仅是指向被复制的内存地址,如果原地址产生扭转,那么浅复制进去的对象也会相应的扭转。
深复制:在计算机中开拓一块 新的内存地址 用于寄存复制的对象。
浅拷贝实例:
// 此递归办法不蕴含数组对象
var obj = {a: 1, arr: [2, 3] };
var shallowObj = shallowCopy(obj);
function shallowCopy(src) {var newobj = {};
for (var prop in src) {if (src.hasOwnProperty(prop)) {newobj[prop] = src[prop];
}
}
return newobj;
}
因为浅复制只会将 对象的各个属性 进行复制,并不会进行递归复制,而 JavaScript 存储对象是存地址的,所以浅复制会导致 Obj.arr 和 shallowObj.arr 指向同一块内存地址:
导致的后果就是:
shallowObj.arr[1] = 5;
console.log(obj.arr[1]); //5
深拷贝实例:
var obj = {
a: 1,
arr: [1, 2],nation: '中国',
birthplaces: ['北京', '上海', '广州']
};
var obj2 = {name: '杨'};
obj2 = deepCopy(obj, obj2);
console.log(obj2);
// 深复制,要想达到深复制就须要用递归
function deepCopy(o, c) {var c = c || {};
for (var i in o) {if (typeof o[i] === 'object') {if (o[i].constructor === Array) {
// 这是数组
c[i] = [];} else {
// 这是对象
c[i] = {};}
deepCopy(o[i], c[i]);
} else {c[i] = o[i];
}
}
return c;
}
而深复制则不同,它不仅将原对象的各个属性一一复制进来,而且将原对象各个属性所 蕴含的对象 也顺次采纳深复制的办法递归复制到新对象上。这就不会存在 obj 和 shallowObj 的 arr 属性指向同一个对象的问题。
这样 obj1 和 obj2 别离领有不同的内存地址,两边的值扭转互不影响。
浅拷贝实现:
var a = [1, 2, 3, 4, 5];
var b = a;
a[0] = 2
console.log(a);
console.log(b);
// 因为 b 浅拷贝 a, ab 指向同一个内存地址(堆内存中存的值)
// b 会随着 a 的变动而变动
//[2, 2, 3, 4, 5]
//[2, 2, 3, 4, 5]
深拷贝实现:
function deepClone(obj) {var newObj = obj instanceof Array ? [] : {};
if (typeof obj !== 'object') {return obj;} else {for (var i in obj) {newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i];
}
}
return newObj;
}
var a = [1, 2, 4, 6, "a", "12", [1, 2]];
var b = deepClone(a);
a[3] = 7;
console.log(a);
console.log(b);
// b 对象并没有因为 a 对象的扭转而扭转,因为 b 深拷贝 a
[1, 2, 4, 7, 'a', '12', [ 1, 2] ]
[1, 2, 4, 6, 'a', '12', [ 1, 2] ]