JavaScript 有哪几种数据类型?请简要描述每种数据类型的特点。
JavaScript 有哪几种数据类型?请简要描述每种数据类型的特点。
核心答案
JavaScript 共有 8 种数据类型,分为两大类:
原始类型(Primitive)— 7 种:
| 类型 | 特点 |
|---|---|
| Number | 双精度 64 位浮点数(IEEE 754),包含整数、浮点数、Infinity、NaN |
| String | 不可变的 UTF-16 编码字符序列 |
| Boolean | 只有 true 和 false 两个值 |
| Undefined | 变量已声明但未赋值的默认值,全局只有一个值 undefined |
| Null | 表示"空值"或"无对象",全局只有一个值 null |
| Symbol | ES6 引入,每个 Symbol 值都是唯一且不可变的,用作对象属性的唯一标识符 |
| BigInt | ES2020 引入,可以表示任意精度的整数,突破 Number 的安全整数限制 |
引用类型(Reference)— 1 种:
| 类型 | 特点 |
|---|---|
| Object | 键值对的集合,Array、Function、Date、RegExp、Map、Set 等都属于 Object |
深入解析
存储机制的本质区别
- 原始类型:值存储在栈内存中(实际上 V8 引擎中小整数 Smi 直接内嵌在指针中),按值访问,赋值时复制值本身。
- 引用类型:值存储在堆内存中,栈中存储的是指向堆内存的引用(地址),赋值时复制的是引用。
栈内存 堆内存
┌──────────────┐ ┌──────────────────┐
│ a = 1 │ │ │
│ b = "hello" │ │ { name: "Tom" } │◄─┐
│ obj ─────────│─────────┤ │ │
│ obj2 ────────│─────────┘ │ │
└──────────────┘ └──────────────────┘
obj 和 obj2 指向同一个堆内存地址
各类型的底层细节
Number:采用 IEEE 754 双精度浮点数,这意味着:
- 安全整数范围:
-(2^53 - 1)到2^53 - 1 - 存在精度问题:
0.1 + 0.2 !== 0.3 - 特殊值:
NaN(唯一一个不等于自身的值)、Infinity、-Infinity、+0和-0
String:不可变(immutable),任何"修改"操作都会创建新字符串。内部使用 UTF-16 编码,一个字符占 2 或 4 字节(代理对)。
Symbol:即使描述相同,每个 Symbol 也是唯一的。Symbol.for() 可以创建全局共享的 Symbol。
BigInt:不能与 Number 混合运算,没有精度上限。
常见误区
- 误区一:
typeof null === "object"。这是 JS 历史遗留的 bug(V8 底层用低位标记类型,null的全零标记被误判为对象),但null是原始类型。 - 误区二:认为 “Function 是独立的数据类型”。
typeof function(){}返回"function",但 Function 在规范中属于 Object 的子类型,不是独立的数据类型。 - 误区三:认为
undefined == null说明它们是一回事。==相等只是规范的特殊规定,它们语义完全不同:undefined表示"未定义",null表示"空值"。
代码示例
// ========== 类型检测 ==========
// typeof 运算符
typeof 42; // "number"
typeof "hello"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" ⚠️ 历史 bug
typeof Symbol(); // "symbol"
typeof 42n; // "bigint"
typeof {}; // "object"
typeof []; // "object" —— 数组也是对象
typeof function(){}; // "function" —— 特殊返回值,但 Function 本质是 Object
// 更准确的类型检测
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(new Date()); // "[object Date]"
// ========== 原始类型 vs 引用类型 ==========
// 原始类型:按值复制
let a = 1;
let b = a;
b = 2;
console.log(a); // 1(不受影响)
// 引用类型:按引用复制
let obj1 = { name: "Tom" };
let obj2 = obj1;
obj2.name = "Jerry";
console.log(obj1.name); // "Jerry"(被修改了)
// ========== 各类型特殊行为 ==========
// Number 精度问题
0.1 + 0.2 === 0.3; // false
0.1 + 0.2; // 0.30000000000000004
Number.MAX_SAFE_INTEGER; // 9007199254740991 (2^53 - 1)
// BigInt
const big = 9007199254740991n + 1n; // 9007199254740992n(精确)
// big + 1; // ❌ TypeError: Cannot mix BigInt and other types
// Symbol 的唯一性
const s1 = Symbol("id");
const s2 = Symbol("id");
s1 === s2; // false
// Symbol.for 全局共享
const s3 = Symbol.for("id");
const s4 = Symbol.for("id");
s3 === s4; // true
// NaN 的特殊性
NaN === NaN; // false
Number.isNaN(NaN); // true
// +0 和 -0
+0 === -0; // true
Object.is(+0, -0); // false
1 / +0; // Infinity
1 / -0; // -Infinity
面试技巧
面试官可能的追问方向:
-
“如何准确判断数据类型?” →
typeof适用于原始类型(注意 null 的 bug),instanceof适用于引用类型,Object.prototype.toString.call()是最准确的通用方案。 -
“null 和 undefined 的区别?” →
undefined是系统级的"未定义",null是程序级的"空值"。函数无返回值时默认返回undefined;需要显式表示"没有对象"时用null。 -
“为什么 0.1 + 0.2 !== 0.3?怎么解决?” → IEEE 754 浮点数精度问题。解决方案:使用
Number.EPSILON比较、转为整数运算、或使用第三方库(如 decimal.js)。 -
“Symbol 的实际应用场景?” → 对象的私有属性键、防止属性名冲突、内置 Symbol(
Symbol.iterator、Symbol.toPrimitive等)定义对象行为。 -
“包装对象是怎么回事?” → 原始类型调用方法时,JS 引擎会临时创建对应的包装对象(
Number、String、Boolean),方法执行完毕后立即销毁。
一句话总结
JavaScript 有 7 种原始类型(Number、String、Boolean、Undefined、Null、Symbol、BigInt)和 1 种引用类型(Object),核心区别在于原始类型按值存储不可变,引用类型按引用存储可变。







