原始值 vs 引用值
Primitive data types vs Reference data types
一句话:原始值存在栈上、直接存值; 引用值存在堆上、栈上只存一个地址。
七种原始类型(背下来,会让你数):string、number、boolean、undefined、null、symbol、bigint。
其余全是引用类型: 对象、数组、函数、Date、Map、Set、正则…… (数组和函数本质都是对象)。
三个可观察的差别:
- 不可变性—— 原始值本身改不了。
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
{} === {}isfalse, 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".