一、基本类型与引用类型的区别
1、基本类型与引用类型在存储上的区别
现在只看栈区和堆区,也假定只是局部变量。 
函数test()被调用时: 1、定义局部变量age,由于age是局部变量,所以在栈中申请内存空间,起名age,给age赋值为25,为基本类型,所以值直接存储在栈中。 2、定义局部变量arr,arr是局部变量,在栈中申请空间,但是由于给arr赋的值不是基本类型,而是引用类型(new出来的),所以需要先在堆中申请空间存放数据18,23,99,再把堆中的地址赋给arr,所以在栈中arr里存方法的是指向堆区的指针。
2、基本类型和引用类型
- 基本类型:就是值类型,即在变量所对应的内存区域存储的是值,如:上面的age变量内存存储的就是值25。
- 引用类型:就是地址类型,存放指向堆中的指针。上面的arr就是引用类型,arr对应的内存中存储着地址,真正的数据存储在地址对应的内存区域里。
二、基本类型和引用类型在赋值时内存的变化
可以理解为,赋值就是在拷贝。
1、基本类型

2、引用类型
 此时,如果在声明一个arr1 = arr,将arr[0]的值修改后,arr1[0]的值也会发生变化。  内存会发生如下变化:  arr和arr1指向的是相同的内存地址。
三、深拷贝和浅拷贝
所谓拷贝,就是赋值,把一个变量赋给另一个变量,就是把变量的内容进行拷贝。把一个对象的值赋给另一个对象,就是把这个对象拷贝一份。
1、基本类型没有问题
因为基本数据类型赋值时,赋的是数据(所以不存在深拷贝和浅拷贝的问题)。
var x = 100;
var y = x;
2、引用类型有问题
引用类型赋值时,赋的值是地址(就是引用类型变量在栈内存中保存的内容)。
var arr = new Array(18, 23, 99);
var arr1 = arr;
如果改变arr1[0] = 33时,arr[0]的值也是33(上面已经测试过了)。原因就是arr和arr1引用了同一块内存区域。这是最简单的浅拷贝,只是把arr的地址拷贝了一份给arr1,并没有把arr的数据也拷贝一份,拷贝的深度不够。
3、用json对象的方式来演示深拷贝和浅拷贝
(1)定义一个json对象(对象的属性也是对象)
var obj = {
id: "909",
name: "小王",
color: new Array("blue", "pink", "yellow")
}
(2)把obj对象复制一份
var obj1 = {};
for(let key in obj) {
obj1[key] = obj[key];
}
obj1.color[0] = "green";
console.log(obj);
console.log(obj1);
 内存: 原始obj对象:  浅拷贝: 
var obj = {
id: "909",
name: "小王",
color: new Array("blue", "pink", "yellow")
}
var obj1 = {};
for(let key in obj) {
if(typeof obj[key] == 'object') {
obj1[key] = [];
for(let i in obj[key]) {
obj1[key][i] = obj[key][i];
}
} else {
obj1[key] = obj[key];
}
}
obj1.color[1] = "black";
console.log(obj);
console.log(obj1);
 内存: 
3.1 如果属性都是json对象,那么采用递归的方式
var p = {
"id": "007",
"name": "Sean",
"wife": {
"id": "008",
"name": "Yibo",
"address": {
"city": "beijing",
"area": "海淀区"
}
}
}
function copyDeep(obj) {
let newObj = {};
for(let key in obj) {
if(typeof obj[key] == 'object') {
newObj[key] = copyDeep(obj[key]);
} else {
newObj[key] = obj[key];
}
}
return newObj;
}
let newP = copyDeep(p);
newP.wife.name = "bobo";
newP.wife.address.city = "shanghai";
console.log(newP);
console.log(p);

3.2 如果属性是数组等非键值对的对象
Array.prototype.copyself = function() {
let arr = new Array();
for(let i in this) {
arr[i] = this[i];
}
return arr;
}
var aObj = {
id: "111",
name: "Sean",
like: new Array("apple", "banana", "lemon")
}
function copyObj(obj) {
let newObj = {};
for(let key in obj) {
if(typeof obj[key] == 'object') {
newObj[key] = obj[key].copyself();
} else {
newObj[key] = obj[key];
}
}
return newObj;
}
var newVal = copyObj(aObj);
newVal.like[0] = "orange";
console.log(aObj);
console.log(newVal);
 参考链接:https://blog.csdn.net/jiang7701037/article/details/98738487
|