了解浅拷贝与深拷贝之前下了解一下堆与栈
堆和栈的区别
其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。
堆和栈都是内存中划分出来用来存储的区域。
栈(stack)为自动分配的内存空间,它由系统自动释放;
堆(heap)则是动态分配的内存,大小不定也不会自动释放。
js的基本数据类型和引入数据类型
基本数据类型:number string boolean undefined null
复杂数据类型(引用类型):object 对象(包括数组和函数)
基本数据类型存放在栈中
- 存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的,所以可以直接访问。
基本数据类型值不可变
- 对数字和布尔值来说显然如此,字符串中所有的方法看上去返回了一个修改后的字符串,实际上返回的是一个新的字符串值。
基本类型的比较是值的比较
- 基本类型的比较是值的比较,只要它们的值相等就认为他们是相等的
比较的时候最好使用严格等,因为 == 是会进行类型转换的,值得注意的是js中||与&&,它们的返回值并不一定是布尔值。JS中整个逻辑运算表达式返回的结果是:“能够决定整个逻辑运算表达式的结果的那个操作数的值”!
var a = 42;
var b = "csdn";
var c = null;
a || b; //返回值是:42,a隐式转换为true---->此时这个表达式的结果由a决定,所以返回a的值
a && b; //返回值是:"csdn" a为true,这个表达式的结果由b决定--->所有返回b的值
c || b; //返回值是:"csdn" c为false,此时表达式的结果由b决定--->返回b的值
c && b;//返回值是:null c为false,决定了表达式的结果--->返回c的值
引用类型存放在堆中
- 引用类型(object)是存放在堆内存中的,变量实际上是一个存放在栈内存的指针,这个指针指向堆内存中的地址。每个空间大小不一样,要根据情况开进行特定的分配
引用类型值可变
var a = [1,2,3];
a[1] = 5;
console.log(a[1]); // 5
引用类型的比较是引用的比较
- js 中的引用类型进行操作的时候,都是操作其对象的引用(保存在栈内存中的指针), 所以比较两个引用类型,是看其的引用是否指向同一个对象。
传值与传址的区别
- 我们进行赋值操作的时候,基本数据类型的赋值(=)是在内存中新开辟一段栈内存,然后再把再将值赋值到新的栈中,基本类型的赋值的两个变量是两个独立相互不影响的变量。
- 引用类型的赋值是传址,只是改变指针的指向,也就是说引用类型的赋值是对象保存在栈中的地址的赋值,这样的话两个变量就指向同一个对象,因此两者之间操作互相有影响。
深拷贝和浅拷贝简单解释
浅拷贝和深拷贝都只针对于引用数据类型
- 浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存;
- 深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象;
区别:
- 浅拷贝只复制对象的第一层属性、深拷贝可以对对象的属性进行递归复制;
赋值(=)、浅拷贝和深拷贝的区别
和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 | |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
深拷贝 | 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 |
浅拷贝:将 B 对象拷贝到 A 对象中,但不包括 B 里面的子对象
var obj = {
name: '小明',
age: 12,
arr: ['aa', 'bb', 'cc'],
eat: function () {
console.log('吃吃吃');
}
}
var obj1 = obj; //obj:原始数据 obj1:赋值操作得到
console.log(obj1.name);
var obj2={};
// 浅拷贝的封装
function extend(a, b) {
for (var key in a) {
b[key] = a[key];
}
}
extend(obj1,obj2);//obj2:浅拷贝得到
console.log(obj1.name, obj2.name);
深拷贝:将 B 对象拷贝到 A 对象中,包括 B 里面的子对象
var objA={
name: '小明',
age: 12,
arr: ['aa', 'bb', 'cc'],
eat: function () {
console.log('吃吃吃');
},
dog:{
name:'小黑',
color:'黑色'
}
}
function extendDeep(a,b) {
for (var key in a){
var item=a[key];
if (Array.isArray(item) ){
b[key]=[];
extendDeep(item,b[key]);
} else if (item instanceof Object ){
b[key]={};
extendDeep(item,b[key]);
} else {
b[key]=a[key];
}
}
}
var objB={};
extendDeep(objA,objB);
console.log(objB);