DrillLab
第 16 / 105 道16 / 105 · #278

原始值 vs 引用值

Primitive data types vs Reference data types

先自己答,再往下看Answer it yourself first

一句话:原始值存在栈上、直接存值; 引用值存在堆上、栈上只存一个地址

七种原始类型(背下来,会让你数):stringnumberbooleanundefinednullsymbolbigint
其余全是引用类型: 对象、数组、函数、DateMapSet、正则…… (数组和函数本质都是对象)。

三个可观察的差别:

  • 不可变性—— 原始值本身改不了。s.toUpperCase()返回新字符串,原来那个没动。
  • 比较—— 原始值比, 引用值比地址。所以{} === {}false[1] === [1] 也是 false
  • 赋值—— 原始值复制一份; 引用值只复制地址,两个变量指向同一个对象。 这就是 #284。

会追问:typeof null 是什么?」——"object",这是个沿用了 30 年的 bug, 因为兼容性一直没修。判断 null 要用x === null
「怎么可靠地判断数组?」——Array.isArray(x), 别用 typeof(会得到 "object")。

In one line: a primitive sits on the stack and holds the value itself; a reference value sits on the heap, and the stack holds only an address.

Seven primitive types (learn the list — they will make you count them): string, number, boolean, undefined, null, symbol, bigint.
Everything else is a reference type: objects, arrays, functions, Date, Map, Set, regexes… (arrays and functions are objects underneath).

Three differences you can observe:

  • Immutability — a primitive value cannot be changed.s.toUpperCase() returns a new string; the original never moved.
  • Comparison — primitives compare by value, references compare by address. So {} === {} is false, and so is [1] === [1].
  • Assignment — a primitive gets copied; a reference copies only the address, so two variables point at the same object. That is #284.

Follow-up: “What is typeof null? ” — "object", a bug that has survived 30 years because fixing it would break too much. Test for null with x === null.
“How do you reliably detect an array?” — Array.isArray(x). Never typeof, which just says "object".

JavaScript值和地址Values and addresses示意Illustrative
1// 原始值:复制值
2let a = 1;
3let b = a;
4b = 2;
5console.log(a); // 1 —— a 没变
6
7// 引用值:复制地址
8let o1 = { n: 1 };
9let o2 = o1; // 同一个对象的第二个遥控器
10o2.n = 2;
11console.log(o1.n); // 2 ← 变了!
12
13// 比较
14console.log({} === {}); // false(两个不同的地址)
15console.log("a" === "a"); // true (比的是值)
16console.log(typeof null); // "object" ← 历史 bug
17console.log(Array.isArray([])); // true ← 判断数组要用这个
1// Primitive value: the value is copied
2let a = 1;
3let b = a;
4b = 2;
5console.log(a); // 1 —— a did not change
6
7// Reference value: the address is copied
8let o1 = { n: 1 };
9let o2 = o1; // a second remote control for the same object
10o2.n = 2;
11console.log(o1.n); // 2 ← it changed!
12
13// Comparing
14console.log({} === {}); // false (two different addresses)
15console.log("a" === "a"); // true (the values are compared)
16console.log(typeof null); // "object" ← a historical bug
17console.log(Array.isArray([])); // true ← use this to test for an array