在JavaScript中,基础类型和引用类型有哪些?存放于哪里?
JavaScript中的数据类型分为两大类:基本类型(原始类型)和引用类型(对象类型)。
基本类型(Primitive types)是直接存储在栈内存中的简单数据段,它们按值访问,具有不可变性。引用类型(Reference types)则是对象,存储在堆内存中,变量实际上存储的是指向堆内存中对象的引用地址(指针)。
重要区别:
-
存储方式:
- 基本类型:值直接存储在变量访问的位置(栈内存)。
- 引用类型:变量存储的是对象的引用地址(指针),实际对象存储在堆内存中。
-
复制行为:
- 基本类型:复制时,会在栈内存中创建一个新的值副本。
- 引用类型:复制时,复制的是引用地址(指针),因此两个变量指向同一个对象。
-
比较方式:
- 基本类型:比较时比较值是否相等。
- 引用类型:比较时比较引用地址是否相等(即是否指向同一个对象)。
-
传递方式:
- 函数参数传递时,基本类型传递的是值的副本,引用类型传递的是引用地址的副本(所以函数内部修改引用类型对象的属性会影响原对象,但重新赋值不会影响原引用)。
以下是详细梳理:
一、基础类型(Primitive Types)
基础类型是不可变(Immutable)的值,直接存储在栈内存(Stack)中(栈帧内),传递时按值拷贝。 ECMAScript标准定义的基础类型有7种:
| 类型 | 描述 | 例子 | typeof 返回值 |
|---|---|---|---|
| String | 字符序列(不可变) | 'hello'、"world" | 'string' |
| Number | 整数/浮点数(双精度) | 123、3.14、NaN | 'number' |
| Boolean | 逻辑值 | true、false | 'boolean' |
| Undefined | 未定义(变量未初始化) | let a; | 'undefined' |
| Null | 空值(故意表示无对象) | let b = null; | 'object'(历史遗留) |
| Symbol | 唯一标识符(ES6+) | Symbol('id') | 'symbol' |
| BigInt | 大整数(ES2020+) | 123n、BigInt(456) | 'bigint' |
二、引用类型(Reference Types)
引用类型是可变(Mutable)的对象,存储在堆内存(Heap)中,栈内存仅存储指向堆的引用地址(类似指针)。 常见的引用类型包括:
| 类型 | 描述 | 例子 | typeof 返回值 |
|---|---|---|---|
| Object | 通用对象(基类) | { name: '小天' } | 'object' |
| Array | 有序列表 | [1, 2, 3] | 'object' |
| Function | 可执行代码块(一等公民) | function() {}、() => {} | 'function'(特殊) |
| Date | 日期对象 | new Date() | 'object' |
| RegExp | 正则表达式对象 | /^[a-z]+$/ | 'object' |
| Map | 键值对集合(ES6+) | new Map() | 'object' |
| Set | 唯一值集合(ES6+) | new Set() | 'object' |
| WeakMap | 弱引用键映射(ES6+) | new WeakMap() | 'object' |
| WeakSet | 弱引用值集合(ES6+) | new WeakSet() | 'object' |
| Error | 错误对象 | new Error('出错了') | 'object' |
| Promise | 异步操作对象(ES6+) | new Promise((res) => res()) | 'object' |
三、核心差异对比
| 特征 | 基础类型 | 引用类型 |
|---|---|---|
| 可变性 | 不可变(无法修改原值) | 可变(可修改属性/元素) |
| 存储位置 | 栈内存(直接存储值) | 堆内存(存储值)+ 栈内存(存储引用) |
| 比较方式 | 值比较(===比较值) | 引用比较(===比较地址) |
| 传递方式 | 按值传递(拷贝值) | 按共享传递(拷贝引用地址) |
四、关键细节说明
- null的特殊处理:
null是基础类型,但typeof null返回'object'(历史遗留bug,ECMAScript未修复以保持兼容性)。 正确判断null应使用=== null: typeof null; // 'object' null === null; // true
- Function的特殊地位:
Function是引用类型(继承自Object),但typeof Function返回'function'(ECMAScript为方便区分函数类型做的特殊处理)。
- 包装对象(Wrapper Objects):
基础类型有对应的包装对象(如String、Number、Boolean),用于提供方法(如str.length)。但原始值本身不是对象: let str = 'hello'; // 基础类型(string) str.length; // 5(自动装箱为String对象,调用后销毁) typeof str; // 'string' typeof new String(str); // 'object'(包装对象)
- 总结
基础类型:简单、不可变、直接存储值,适合表示原子数据。 引用类型:复杂、可变、通过引用访问,适合表示结构化数据。 理解两者的差异是掌握JavaScript内存管理、变量传递、状态管理的关键(比如Vue的data函数设计就依赖于引用类型的特性)。