Skip to main content

JavaScript 数据类型全解析:从内存机制到上下文行为

✅ 核心结论

  • 分类标准:JavaScript 数据类型分为基本数据类型(存放在栈,值不可变)和引用数据类型(存放在堆,通过地址引用)。
  • 内存特征:基本类型是“值传递”,修改互不影响;引用类型是“址传递”,多个变量可共享并修改同一块内存数据。
  • 动态特性:JS 是弱类型语言,数据会根据执行上下文(运算、方法调用等)自动进行类型转换或临时包装。
  • 记忆口诀:“四基一空一未定,符号大数后加进;对象函数与数组,引用类型在堆里。”

🧠 关键概念

  • 基本数据类型 (7种)
    • Number(含 NaN/Infinity)、StringBooleanUndefinedNull
    • ES6+ 新增:Symbol(唯一标识)、BigInt(大整数)。
  • 引用数据类型Object(基石),衍生出 ArrayFunctionDateRegExp 等。
  • 隐式类型转换:在字符串上下文(+)、数值上下文(-*/)或布尔上下文(if判断)中,JS 会自动转换数据类型。
  • 包装对象 (Wrapper Object):当基本类型调用属性或方法时,JS 会临时将其包装成对象,调用完后立即销毁。

📌 适用场景

  • 唯一属性名:使用 Symbol 定义对象属性,避免命名冲突。
  • 高精度计算:处理超过 $2^{53}-1$ 的大整数时必须使用 BigInt
  • 精确类型判断
    • 基础判断用 typeof
    • 数组判断用 Array.isArray()
    • 全能判断用 Object.prototype.toString.call()
  • 复杂数据结构:利用引用类型的特性,通过 ObjectArray 组织结构化数据。

⚠️ 常见误区

  • typeof null:结果为 "object",这是 JS 的历史遗留 Bug,不代表 null 是对象。
  • 引用共享陷阱:将一个对象赋值给新变量时,修改新变量的属性会同步影响原对象。
  • typeof 局限性:无法区分数组、对象和 null,它们都会返回 "object"
  • 比较差异:基本类型比较的是“值”,引用类型比较的是“内存地址”。即使两个对象内容完全一样,{} === {} 也是 false

✅ 示例

1. 引用共享与基本类型区别

// 基本类型:值拷贝
let x = 10;
let y = x;
y = 20; // x 依然是 10

// 引用类型:地址共享
let obj1 = { val: 10 };
let obj2 = obj1;
obj2.val = 20; // obj1.val 变成了 20

2. 隐式转换上下文

"10" + 5;  // "105" (字符串上下文)
"10" - 5; // 5 (数值上下文)
!! "hello"; // true (布尔上下文)

3. 精确类型判断

Object.prototype.toString.call([]);      // "[object Array]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(new Date()); // "[object Date]"