你有没有想过,为什么let a = 1和let b = {name: 'Tom'}在赋值后表现不同?为什么修改a不影响b,但修改对象属性却会?今天,我们就来扒一扒JavaScript中变量们的"居住条件"——数据存储机制。
一、数据类型:变量的"身份标签"
JavaScript里的变量分两大派系:
1. 原始类型(基本类型):"单身贵族"们
这些是JavaScript里的"基本居民",共有7位:
string:字符串,比如'hello'number:数字,包括整数和小数boolean:布尔值,只有true和falsenull:空值(虽然typeof返回'object',但它真的是原始类型)undefined:未定义symbol:唯一值,即使描述相同也不等bigint:大整数,专门处理超出安全范围的数字
原始类型就像"单身贵族",性格独立,赋值时是值传递——复制一份全新的自己。就像你复制了一篇文章,修改副本不会影响原文。
let a = 1;
let b = a;
a = 2;
console.log(a); // 2
console.log(b); // 1,不受a的影响
2. 引用类型(复杂类型):"拖家带口"的大户
这些是JavaScript里的"大家庭",主要有:
Object:对象Array:数组function:函数Date:日期对象
引用类型就像"拖家带口"的大户,赋值时是引用传递——传递的是地址(引用)。就像两个人共用一个快递柜的钥匙,你放东西进去,另一个人也能看到。
let obj1 = {name: '张三'};
let obj2 = obj1;
obj1.name = '李四';
console.log(obj2.name); // '李四',跟着变了
二、JavaScript:一门"随性"的语言
JavaScript是动态弱类型语言,这是什么意思?
- 动态类型:变量不需要提前声明类型,赋值时才确定。就像你点奶茶,想喝什么临时决定,不需要提前预约。
- 弱类型:支持隐式类型转换。就像你说"我要奶茶",店员可能会默认给你加珍珠,自动给你转换了。
let a = '123';
a = 456; // 没问题,变量类型说变就变
let b = '1' + 2; // '12',字符串拼接
let c = '1' * 2; // 2,自动转成数字计算
三、内存空间:变量们的"住所"
V8引擎在执行JS代码时,会开辟三种内存空间,就像不同档次的住所:
1. 代码空间:"公共图书馆"
存放代码本身的文本,就像图书馆里的书籍,供CPU读取和执行。
2. 栈空间:"胶囊公寓"
存放原始类型数据和引用类型的地址,特点是容量小、访问快。就像市中心的胶囊公寓,虽然小但位置好,适合单身贵族(原始类型)和快递柜钥匙(引用地址)。
3. 堆空间:"豪华别墅"
存放引用类型的具体内容,特点是容量大、结构复杂。就像郊外的豪华别墅,空间大,可以住下整个大家庭(对象的所有属性和方法)。
四、实战演示:变量们的"搬家"过程
来看个经典例子,理解内存中的变量行为:
function foo(person) {
person.age = 20; // 修改传入对象的属性
person = {name: '刘洋'}; // 重新赋值
return person;
}
let p1 = {name: '张三', age: 18};
let p2 = foo(p1);
console.log(p1); // {name: '张三', age: 20}
console.log(p2); // {name: '刘洋'}
这里的关键是:
person参数一开始指向p1的地址(同一个别墅),所以修改person.age会影响p1- 但当
person = {name: '刘洋'}时,person就换了一个新地址(搬去了另一个别墅),和p1没关系了 - 所以
p2拿到的是新别墅的地址,而p1还在原来的别墅里,只是年龄被改了
五、Symbol:数据界的"身份证"
Symbol是个特别的原始类型,它的特点是唯一性——即使描述相同,也是不同的值。就像身份证号,哪怕两个人同名同姓,身份证号也不一样。
let s1 = Symbol('hello');
let s2 = Symbol('hello');
console.log(s1 === s2); // false,虽然描述相同,但不是同一个值
这在需要唯一标识符的场景特别有用,比如对象的唯一属性名。
总结:理解数据存储,写出更稳健的代码
- 原始类型是值传递,赋值后互不影响
- 引用类型是引用传递,赋值后共享同一个内存地址
- JavaScript的动态弱类型特性让它很灵活,但也容易出错
- 栈空间存原始类型和引用地址,堆空间存引用类型的具体内容
理解这些概念,能帮你更好地解释代码中的一些"奇怪"现象,写出更稳健、更高效的JavaScript代码。下次遇到变量赋值问题,记得想想变量们的"居住条件"哦!