面試官問「JS 的型別」時,到底想聽到什麼?
這不是一篇基礎教學,而是一次思維升級。如果你只停留在「知道有哪些型別」的層面,那你和面試官之間還差一個 V8。
面試官問:「JavaScript 有哪些資料型別?」
初級回答(大部分人):
「有 string、number、boolean、null、undefined、object……還有 symbol?」
面試官(內心):背八股文呢?
進階回答(你):
「JS 的型別可以分為兩大類——基本型別和參照型別。這種分類不是拍腦袋定的,而是由 V8 引擎的記憶體管理機制決定的。基本型別體積小,直接存在堆疊裡;參照型別體積不定,存在堆積裡,堆疊裡只存 8 位元組的位址指標。這樣做的好處是——」
面試官(眼睛一亮):這人懂底層。
差距在哪裡? 前者只是列舉,後者是解釋為什麼。
基本型別(7 種)——值直接存堆疊裡
類型 例子 常見坑 string 'hello' — number 42 NaN 也是 number 型別 boolean true !! 是布林轉換的快捷方式 undefined let a 宣告未賦值 null null ⚠️ typeof null → 'object' bigint 10n ES2020 才加入 Symbol Symbol('id') 每次呼叫都是唯一值
參照型別(常見 4 種)——值存堆積裡,堆疊存位址
類型 例子 說明 Object { name: 'Alice' } 一切參照型別的祖宗 Array [1, 2, 3] typeof [] → 'object' Function function() {} JS 中函式也是物件 Date new Date() ⚠️ Date() 不是 Date 型別,是字串!
七個基本用一個口訣記住:
「宋(string)數(number)不(boolean)定(undefined)空(null)大(bigint)象(Symbol)」
七種基本型別,一個不少。
參照型別只記一句話:
「除了以上七種,其他全是物件」
自己跑一下這三行程式碼,你就懂了:
javascript 体验AI代码助手 代码解读复制代码// 場景 A:基本型別賦值
let a = 10;
let b = a;
b = 20;
console.log(a); // 猜猜是 10 還是 20?
javascript 体验AI代码助手 代码解读复制代码// 場景 B:參照型別賦值
let objA = { count: 10 };
let objB = objA;
objB.count = 20;
console.log(objA.count); // 猜猜是 10 還是 20?
答案:
10 ✅ — 基本型別賦值是複製值,a 和 b 沒關係了20 ⚠️ — 參照型別賦值是複製位址,objA 和 objB 指向同一個物件記法:基本型別像影印件——改一個不影響另一個;參照型別像捷徑——不管從哪個入口進去,改的都是同一個檔案。
這是很多人知道「是什麼」卻說不清「為什麼」的關鍵。
ini 体验AI代码助手 代码解读复制代码執行這段程式碼時,V8 在記憶體裡做了什麼:
let name = 'GGBond';
let age = 20;
let girlFriend = {
name: 'feifei',
hobbies: ['coding', 'reading']
};
畫出來是這樣的:
css 体验AI代码助手 代码解读复制代码┌────────── 堆疊(Call Stack)──────────┐
│ │
│ name: 'GGBond' ← 字串直接存 │
│ age: 20 ← 數字直接存 │
│ girlFriend: ● ————————┐ │
│ │ │
└─────────────────────│────────────────┘
│ 參照位址(8 位元組)
▼
┌────────── 堆積(Heap)────────────────┐
│ │
│ { name: 'feifei', │
│ hobbies: ● ————→ ['coding', │
│ } 'reading'] │
│ │
└──────────────────────────────────────┘
❌ 錯誤方案:所有資料都放堆疊裡
如果 girlFriend 這個大物件也放進堆疊:
❌ 錯誤方案:所有資料都放堆積裡
如果連 age = 20 也要去堆積裡分配:
✅ V8 的選擇:混合儲存
体验AI代码助手 代码解读复制代码基本型別(小、輕) → 堆疊 — 快就完了
參照型別(大、不定)→ 堆積 — 堆疊不會爆
參照位址(8 位元組) → 堆疊 — 查詢時透過位址找資料
一句話總結:堆疊管速度,堆積管容量。V8 用最小代價換來了最大效率。
typeof —— 適合基本型別(除 null)
javascript 体验AI代码助手 代码解读复制代码typeof 'hello' // 'string'
typeof 42 // 'number'
typeof true // 'boolean'
typeof undefined // 'undefined'
typeof Symbol() // 'symbol'
typeof 10n // 'bigint'
typeof null // 'object' ← 歷史遺留 bug
typeof [] // 'object' ← 陣列也是 object
typeof {} // 'object'
規律:除了 null,基本型別的 typeof 都能對上。
instanceof —— 適合參照型別
javascript 体验AI代码助手 代码解读复制代码[] instanceof Array // true
{} instanceof Object // true
new Date() instanceof Date // true
'hello' instanceof String // false ❌ 基本型別不行
注意:
[] instanceof Object也是 true!因為原型鏈上能找到 Object。
Object.prototype.toString —— 萬能方法
javascript 体验AI代码助手 代码解读复制代码function getType(v) {
return Object.prototype.toString.call(v).slice(8, -1);
}
getType('hello') // 'String'
getType(null) // 'Null'
getType([]) // 'Array'
getType(new Date()) // 'Date'
getType(new Map()) // 'Map'
javascript 体验AI代码助手 代码解读复制代码function typeOf(value) {
// null 單獨處理
if (value === null) return 'null';
// 基本型別用 typeof
const base = typeof value;
if (base !== 'object' && base !== 'function') return base;
// 參照型別用 toString
const tag = Object.prototype.toString.call(value);
return tag.slice(8, -1).toLowerCase();
}
// 測試
typeOf('hello') // 'string'
typeOf(null) // 'null' ✅ 修復了 typeof null 的 bug
typeOf([]) // 'array'
typeOf(new Date())// 'date'
typeOf(new Map()) // 'map'
javascript 体验AI代码助手 代码解读复制代码let num = 10;
let str = 'hello';
let obj = { key: 'value' };
function add(x, y) {
return x + y;
}
let result = add(num, 20);
V8 的執行步驟:
less 体验AI代码助手 代码解读复制代码Step 1:建立呼叫堆疊(Call Stack)
Step 2:建立全域執行環境,壓入堆疊底部
Step 3:執行宣告(建立階段)
├── num → 堆疊中存 10
├── str → 堆疊中存 'hello'
├── obj → 堆積中建立 {key:'value'},堆疊存位址 @001
├── add → 堆積中存函式體,堆疊存位址 @002
└── result → 堆疊中存 undefined
Step 4:執行 add(num, 20)
├── 建立函式執行環境,入堆疊
├── x=10, y=20 存入堆疊中(函式的堆疊)
├── 執行 x + y → 回傳 30
└── 函式執行環境出堆疊
Step 5:result = 30
javascript 体验AI代码助手 代码解读复制代码function infinite() {
return infinite();
}
infinite();
會。 每呼叫一次就建立一個執行環境入堆疊,堆疊是有限的,最終:
scss 体验AI代码助手 代码解读复制代码┌───────── 呼叫堆疊 ─────────┐
│ infinite() // 第10000次 │
│ infinite() // 第9999次 │
│ ... │
│ infinite() // 第1次 │
│ 全域執行環境 │
└──────────────────────────┘
RangeError: Maximum call stack size exceeded
這就是「爆堆疊」——參照型別放堆積裡而不是堆疊裡,正是為了防止這種溢位。
這篇文章沒有講什麼高深的東西,而是用「為什麼」把你知道的碎片知識串了起來。
JS 型別的核心其實就三句話:
能說出這三句,面試官就知道你不只是學過,還思考過。
覺得有用的話按讚 👍 收藏 ⭐,讓更多人看到。
你的面試路上還遇過什麼離譜的 JS 型別題?留言區告訴我。