001-JavaScript 数据类型

JavaScript 数据类型

两大分类

  1. 基本类型(Primitive Types)
  • string:字符串
  • number:数字
  • boolean:布尔值
  • null:空值
  • undefined:未定义
  • symbol(ES6新增):符号,表示唯一值
  • bigint(ES2020新增):大整数,表示任意大的整数
  1. 引用类型(Reference Types)
  • Object:对象
  • 包括:Array, Function, Date, RegExp, Map, Set, WeakMap, WeakSet等。

基本类型 vs 引用类型的核心区别

特性 基本类型 引用类型
存储方式 栈内存(直接存储值) 堆内存(存储地址,栈中存指针)
赋值行为 复制值(新旧变量互不影响) 复制指针(指向同一内存对象)
比较方式 值比较('a' === 'a'true 引用比较({} === {}false
函数传参 传递值的副本 传递指针副本(内部修改影响外部对象)
动态属性 不可添加属性 可动态添加/删除属性
内存管理 变量销毁时自动回收 需垃圾回收机制处理

复习一下数据结构:
1.栈(Stack)
逻辑结构:一种线性结构,遵循后进先出(LIFO)原则,仅允许在表的一端(栈顶)进行插入(push)和删除(pop)操作。
物理实现:通常通过数组或链表实现,数据连续存储,操作仅涉及栈顶元素。
典型操作:
push:将元素压入栈顶。
pop:弹出栈顶元素。
peek:查看栈顶元素(不弹出)。
2.堆(Heap)
逻辑结构:一种树形结构,通常为完全二叉树,满足堆性质(父节点的值大于或等于子节点的值称为最大堆,反之为最小堆)。
物理实现:通过数组实现,逻辑上模拟树结构,物理上连续存储。
典型操作:
insert:插入元素并保持堆性质。
extract:移除根节点(最大或最小值)。
heapify:调整节点位置以维护堆性质。

示例说明

1
2
3
4
5
6
7
8
9
10
11
// 基本类型 - 值复制
let num1 = 10;
let num2 = num1; // 值复制
num2 = 20;
console.log(num1); // 10(不受影响)

// 引用类型 - 指针复制
let obj1 = { count: 10 };
let obj2 = obj1; // 指针复制
obj2.count = 20;
console.log(obj1.count); // 20(同步修改)

Symbol 详解

作用:创建唯一的、不可变的值,常用作对象属性的键(避免命名冲突)。
特性

  • 通过 Symbol([description]) 创建
  • 即使描述相同,Symbol 值也不同:Symbol('id') !== Symbol('id')
  • 不可枚举(for...in 跳过),需用 Object.getOwnPropertySymbols() 获取
    1
    2
    3
    const sym1 = Symbol('id');
    const sym2 = Symbol('id');
    console.log(sym1 === sym2); // false(唯一性)

应用场景:

  1. 唯一对象属性键
    避免第三方库属性名冲突:

    1
    2
    3
    4
    const user = {
    name: "Alice",
    [Symbol('id')]: 123 // 隐藏属性
    };
  2. 模拟私有属性
    (需配合 Object.defineProperty 或闭包实现真正私有):

    1
    2
    3
    4
    5
    6
    const _password = Symbol('password');
    class User {
    constructor(password) {
    this[_password] = password;
    }
    }
  3. 全局 Symbol 注册表
    跨模块共享 Symbol:

    1
    2
    3
    4
    5
    // module1.js
    const id = Symbol.for('global_id');
    // module2.js
    const sameId = Symbol.for('global_id');
    console.log(id === sameId); // true
  4. 内置 Symbol 值
    定制对象行为(如迭代器):

    1
    2
    3
    4
    5
    6
    7
    const obj = {
    [Symbol.iterator]: function* () {
    yield 1;
    yield 2;
    }
    };
    console.log([...obj]); // [1, 2]

应用场景

场景 说明 示例
唯一对象属性键 由于Symbol值是唯一的,因此可以用来作为对象属性的键,避免属性名冲突 const obj = { [Symbol('id')]: 123 };
模拟私有属性 配合闭包实现伪私有属性(虽然ES6的类并没有真正的私有属性,但使用Symbol可以在一定程度上模拟私有属性,因为外部无法直接访问Symbol属性) const _key = Symbol(); class Safe { constructor(k) { this[_key] = k; } }
全局Symbol注册表 跨模块/文件共享Symbol //module1.js Symbol.for('global'); //module2.js Symbol.for('global');
内置Symbol行为定制 实现迭代协议等特殊行为(ES6提供了一些内置的Symbol值,用于改变语言内部行为,如Symbol.iterator(定义迭代器)、Symbol.toStringTag const iterable = { [Symbol.iterator]: function*() { yield 1; } };
定义常量 用于定义一组常量,保证这组常量的值都是不相等的。 const LOG_LEVEL = {DEBUG: Symbol('debug'),INFO: Symbol('info'),ERROR: Symbol('error')};

BigInt 详解

特性

作用:表示任意精度的整数,解决 Number 类型无法安全表示的大整数问题(Number.MAX_SAFE_INTEGER = 2^53 - 1)。
特性

  • 字面量加 n 后缀:12345678901234567890n
  • 通过 BigInt() 函数转换:BigInt("9007199254740993")
  • 不能与 Number 直接运算(需显式转换)

应用场景:

  1. 大整数运算
    金融、科学计算等需要高精度的场景:

    1
    2
    3
    const big1 = 9007199254740993n;
    const big2 = 1n;
    console.log(big1 + big2); // 9007199254740994n
  2. 大 ID 处理
    数据库返回的 64 位 ID(如 Snowflake 算法生成的 ID):

    1
    const id = BigInt("12345678901234567890"); // 超出 Number 安全范围
  3. 高精度时间戳
    纳秒级时间戳运算:

    1
    2
    3
    4
    const start = process.hrtime.bigint(); // Node.js
    // 执行操作...
    const end = process.hrtime.bigint();
    console.log(`耗时: ${(end - start) / 1000000n} 毫秒`);
  4. 大数加密/哈希
    密码学中的大整数运算:

    1
    const prime = BigInt("0xFFFFFFFFFFFFFFFFC90FDAA...");

注意事项:

  • 不支持 Math 对象的方法
  • 与 Number 比较时类型不同(1n === 1 → false
  • JSON 序列化需自定义处理(默认抛出错误)
1
2
3
4
5
6
// 类型转换
console.log(1n == 1); // true(值相等)
console.log(1n === 1); // false(类型不同)

// 运算限制
console.log(Math.sqrt(16n)); // TypeError(不支持Math方法)

总结对比

类型 核心特性 典型应用场景
Symbol 唯一性、不可枚举、避免冲突 对象元编程、私有属性模拟、库开发
BigInt 任意精度、突破Number安全限制 大整数ID、金融计算、高精度时间处理