JS数据类型三大类:
1.原始数据类型:数值类型number 字符串类型string,boolean类型,存放在栈内存
2.特殊数据类型:null,undifined,存放在栈内存
3.引用数据类型:对象数据类型object,array数组,function函数。存放在堆内存里面
栈内存 number / string / boolean null / undifined 1.声明变量就会在栈内存中开辟内存空间,变量则是对应的内存地址 2.变量的赋值则是存放在对应的内存空间中的具体 3.如果变量的值是原始数据类型或者特殊数据类型直接存放在栈内存 | 堆内存 object / array / function 4.引用数据类型存放在堆内存,引用数据类型赋值给变量,是把引用数据类型在堆内存地址赋值给变量 |
var a = { // --> 会在栈中创建一个a内存空间 ,在堆中创建一个内存地址
name: "nana",
age: 14,
}
var b // --> 创建一个b对象
b = a // --> 把a变量存的内存地址赋值给b ,这时b和a变量都是指向同一个堆内存地址
对于引用数据类型,直接赋值是一种浅拷贝,只拷贝了内存地址。
堆内存的数据变化之后,其他引用该内存地址的数据也会发生变化。
<script>
var p1 = {
name: "nana",
age: 14,
addr: "xxx号",
}
var p2 = p1; //把p1的内存地址赋值给p2
console.log(p1)
// 判断p1和p2的内存地址是否相等
console.log(p1 === p2); //true --> 应用数据类型比较的是内存地址
p2.name = "li"; //单修改了p2中name属性的值,但是内存地址没有改变
console.log(p2);
//由于p2浅拷贝了p1的内存地址,p2的值发生变化时,p1对应的对象值也会改变
console.log(p1);
console.log(p1 === p2); //true --> 应用数据类型比较的是内存地址
</script>
如果不想要浅拷贝(拷贝内存地址)。
需要创建一个新的内存地址,然后拷贝对象的属性和值即深拷贝
<script>
var p1 = {
name: "nana",
age: 14,
addr: "xxx号",
}
var p3 = {}; //在堆中创建一个新的内存地址存放对象
for (var a in p1) { //遍历p1中的属性
p3[a] = p1[a]; //把p1中的属性赋值给p3中的属性
}
console.log(p1 === p3); //false --> p3和p1的内存地址不一样
p3.name = "nananan"; //修改了p3中的name值
console.log(p3); //输出的name值为nananan
console.log(p1); //输出的name值为nana 因为内存地址不一样
</script>