2. 原始类型与引用类型赋值行为对比

原始类型与引用类型赋值行为对比 学习卡片

赋值行为对比实验设计

本实验对七种数据类型分别执行“赋值 → 修改副本 → 观察原变量”三步操作,通过输出结果判断赋值时传递的是值本身还是内存地址。核心判断依据:若修改副本后原变量不变,则为值传递;若原变量同步变化,则为引用传递。

原始类型 vs 引用类型 — 赋值行为对比 原始类型(值传递) number let a = 10; let b = a; b = 99; → a = 10, b = 99 独立副本 string let s1 = "hello"; let s2 = s1; s2 = "world"; → s1 = "hello" 独立副本 boolean let f1 = true; let f2 = f1; f2 = false; → f1 = true 独立副本 null / undefined let n1 = null; let n2 = n1; n2 = "changed"; → n1 = null 独立副本 引用类型(引用传递) object let o1 = { name: "Tom" }; let o2 = o1; o2.name = "Jerry"; → o1.name = "Jerry" 共享地址 array let arr1 = [1, 2, 3]; let arr2 = arr1; arr2.push(4); → arr1 = [1,2,3,4] 共享地址 内存示意 o1 ──┐ o2 ──┘──→ 堆内存 { name: "Jerry" } 两个变量指向同一对象

实验代码与输出记录

以下代码对每种类型执行赋值与修改操作,通过 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布尔值副本不变值传递
nullnull 副本不变值传递
undefinedundefined 副本不变值传递
object堆内存地址同步变化引用传递
array堆内存地址同步变化引用传递
关键区分:原始类型的变量直接存储值本身,赋值时复制一份独立的值;引用类型的变量存储的是堆内存地址,赋值时复制的是地址,两个变量最终指向同一个对象。因此修改引用类型副本的属性或元素,原变量会同步变化。
常见误区:使用 const 声明对象后,仍然可以修改对象的属性(如 obj.name = "new"),因为 const 限制的是变量绑定的地址不可变,而非对象内部内容不可变。若需完全不可变,需使用 Object.freeze() 或展开运算符创建新对象。