2. 原始类型与引用类型赋值行为对比
赋值行为对比实验设计
本实验对七种数据类型分别执行“赋值 → 修改副本 → 观察原变量”三步操作,通过输出结果判断赋值时传递的是值本身还是内存地址。核心判断依据:若修改副本后原变量不变,则为值传递;若原变量同步变化,则为引用传递。
实验代码与输出记录
以下代码对每种类型执行赋值与修改操作,通过 console.log 输出原变量和副本变量的值,直接观察差异。
// ===== 原始类型:值传递 =====
let numA = 10;
let numB = numA;
numB = 99;
console.log("number:", numA, numB); // 10 99
let strA = "hello";
let strB = strA;
strB = "world";
console.log("string:", strA, strB); // hello world
let boolA = true;
let boolB = boolA;
boolB = false;
console.log("boolean:", boolA, boolB); // true false
let nullA = null;
let nullB = nullA;
nullB = "changed";
console.log("null:", nullA, nullB); // null changed
let undefA = undefined;
let undefB = undefA;
undefB = "assigned";
console.log("undefined:", undefA, undefB); // undefined assigned
// ===== 引用类型:引用传递 =====
let objA = { name: "Tom", age: 20 };
let objB = objA;
objB.name = "Jerry";
console.log("object:", objA.name, objB.name); // Jerry Jerry
let arrA = [1, 2, 3];
let arrB = arrA;
arrB.push(4);
console.log("array:", arrA, arrB); // [1,2,3,4] [1,2,3,4]
对比结论
| 类型 | 赋值传递内容 | 修改副本后原变量 | 结论 |
|---|---|---|---|
| number | 数值副本 | 不变 | 值传递 |
| string | 字符串副本 | 不变 | 值传递 |
| boolean | 布尔值副本 | 不变 | 值传递 |
| null | null 副本 | 不变 | 值传递 |
| undefined | undefined 副本 | 不变 | 值传递 |
| object | 堆内存地址 | 同步变化 | 引用传递 |
| array | 堆内存地址 | 同步变化 | 引用传递 |
关键区分:原始类型的变量直接存储值本身,赋值时复制一份独立的值;引用类型的变量存储的是堆内存地址,赋值时复制的是地址,两个变量最终指向同一个对象。因此修改引用类型副本的属性或元素,原变量会同步变化。
常见误区:使用
const 声明对象后,仍然可以修改对象的属性(如 obj.name = "new"),因为 const 限制的是变量绑定的地址不可变,而非对象内部内容不可变。若需完全不可变,需使用 Object.freeze() 或展开运算符创建新对象。