小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
在JS世界中,数据类型分为基础数据类型和引用数据类型,由于不同 JS 的数据类型在初始化之后,会存储在不同的内存中,导致很多刚接触JS的同学会产生一些困惑,分不清楚按值传递和按引用传递的区别以及修改时会带来怎样的影响
数据类型及其存储方式
JS中将数据类型分为两类:
基础数据类型:共7种,分别为Number、String、Boolean、Null、Undefined、Symbol、BigInt
引用数据类型:只有一种Object类型,但其会细分为Array、Date、Function、RegExp等
不同的数据类型存储方式:
基础数据类型存储在栈内存中,当其被引用或者拷贝的时候,会创建一个完全相等的变量,改变的时候互不影响
引用数据类型存储在堆内存中,存储的是指针地址,当其被引用或者拷贝的时候创建的是一个指向同一个指针地址,相当于共享同一份数据,修改数据时修改的是同一份数据,等同于全部指向其指针地址的数据都是修改后的数据
不少同学在开始接触到这个概念时会产生困惑,先看两个例子来理解一下
let str = 'nordon';
let newStr = str;
newStr = 'wy';
console.log(str); // nordon
console.log(newStr); // wy
两次输出的内容是不一致的,后面的修改对原有的数据不造成任何的影响
上面的过程相当于我创建了一个文件A,内容是nordon,之后我将文件拷贝一份,生成一份新的文件B,此时文件B的内容还是nrdon,然后打开新的文件B将其内容修改为wy,此时两个文件内容是不一样的
let obj = {
name: 'nordon',
age: 18
};
let newObj = obj;
newObj.name = 'wy';
console.log(obj); // { name: 'wy', age: 18 }
console.log(newObj); // { name: 'wy', age: 18 }
两次打印的结果是相同的,因为obj和newObj指向的是同一份内存地址
上面的过程相当于我创建了一个文件A,内容是**{ name: 'nordon', age: 18 },让后将文件A创建一个快捷访问链接A(windows 系统的都懂 😂),此时点击快捷访问链接A就可以打开文件A,那么此时根据快捷访问链接A拷贝一份,生成一个新的快捷访问链接B,此时通过B打开文件,将内容修改为{ name: 'wy', age: 18 }**,因为无论通过那个快捷访问链接打开的都是同一份文件A,那么修改的内容是共享的
let obj = {
name: 'nordon',
age: 18
};
const changeName = (_obj) => {
_obj.name = 'wy';
_obj = { // _obj 重新赋值一个对象
name: 'hellobike',
age: 5
};
return _obj;
}
const newObj = changeName(obj);
console.log(obj); // {name: 'wy', age: 18}
console.log(newObj) // {name: 'hellobike', age: 5}
两次打印的结果是不同的,按照第一反应传递的是引用数据类型,那么obj应该是和newObj保持一致的,因为其指针都是指向同一份地址的,是共享数据的
因为在_obj重新赋值一个对象时,是将一份新的指针地址赋值给__obj,断开了之前的指针,为其重新创建了一份地址,这样其和通过函数传递的obj便不再共享同一份数据
读到这里的同学若是还有些迷惑,可以根据前面创建文件和快捷访问链接的例子来套用到此问题上