JS数据结构
JavaScript 的数据类型可以分为两大类:原始类型(Primitive Type)和对象类型(Object Type)。
原始类型:
- String:用于表示文本数据。例如:"Hello, World"。
- Boolean:用于表示真或假。有两个值:true 和 false。
- Undefined:表示未定义的值。未初始化的变量默认值为 undefined。
- Null:表示没有任何有效值。
- Symbol:在 ES6 中引入,表示唯一的标识符。
- BigInt:在 ES10 中引入,用于存储大整数。
引用类型
- Object:用于存储键值对集合。
- Array:用于存储元素集合。
- Function:用于执行特定任务的代码块。
- Date:用于处理日期和时间。
- RegExp:用于执行正则表达式匹配。
- 其他内置对象类型,例如 Map、Set、Promise 等。
内存表现
原始类型
对于原始类型(Undefined、Null、Boolean、Number、String、Symbol和BigInt),它们的值会被直接存储在栈内存中。每个原始类型的值都占用固定大小的内存空间,例如,一个 Number 类型的值在内存中占据 64 位。原始类型的值由于大小固定,可以直接按值访问,这使得访问速度非常快。
引用类型
对于引用类型,如 Object 和 Array,它们在内存中的表现比较复杂。当你创建一个对象或数组,实际存储的是一个内存地址——这个地址指向堆内存中的一块区域,这块区域存储了对象的属性。这种内存地址的存储方式意味着当你创建一个对象或数组时,变量实际存储的是引用(或指针)而不是实际的值。
比如,当你写下 let obj = {a: 1};,实际发生的是:在堆内存中创建了一个新的对象,其属性 a 的值为 1;然后,将这个对象在堆内存中的地址保存在栈内存中的 obj 变量中。当你需要访问 obj.a 时,JavaScript 会先查找 obj 在栈内存中的地址,根据这个地址找到堆内存中的对象,然后返回其属性 a 的值。
这种方式比原始类型在内存中的表现要消耗更多的内存,但它允许你创建复杂的数据类型并进行更复杂的操作。
他们有什么区别呢
原始类型和引用类型在 JavaScript 中的主要区别如下:
存储位置
- 原始类型的值存储在**栈(Stack)**中,因为这些类型的大小固定。
- 引用类型(对象、数组和函数)的值是对象,存储在**堆(Heap)**中,因为这些类型的大小不固定。
访问机制
- 当你访问原始类型的值时,是直接按值访问。
- 当你访问引用类型的值时,实际上访问的是它们在堆内存中的地址,或者说是对该地址的引用而不是实际的对象本身。
复制变量
- 当你将一个原始类型的值复制给新变量,复制的是实际的值。
- 当你将一个引用类型复制给新变量,复制的是内存地址