吃透 JS 八大数据类型与内存原理,从代码到底层一站式复习

一文吃透 JavaScript 八大数据类型 + 内存存储原理(附实战代码)

前言

学习 JavaScript 绕不开数据类型内存存储机制 ,这也是前端基础面试高频考点。很多同学分不清 nullundefined、搞不懂原始值与对象的赋值区别、疑惑小数精度丢失、大整数溢出等问题。

本文结合实战代码 + 内存原理 + 场景解析,完整梳理 JS 8 大数据类型、栈 / 堆内存分配、赋值机制、常见坑点,适合日常复习与查漏补缺。

一、JS 总共有多少种数据类型?

按照 ECMA-262 规范,目前 JavaScript 一共分为 8 种数据类型 ,整体划分为 ** 原始数据类型(基本类型) 引用数据类型(复杂类型)** 两大类。

1. 原始数据类型(Primitive 基本类型)

7 种 ,ES6 之后新增 SymbolBigInt

  1. number 数值类型
  2. string 字符串类型
  3. boolean 布尔类型
  4. null 空值类型
  5. undefined 未定义类型
  6. Symbol 符号类型(ES6 新增)
  7. BigInt 大整数类型(ES6+ 新增)

2. 引用数据类型(复杂类型)

1 种

  • object 对象类型细分:普通对象 {}、数组 []、函数、正则、日期等,本质都属于 object

补充:ES6 之前 JS 只有 6 种数据类型 (无 SymbolBigInt)。


二、内存底层:栈内存 & 堆内存(核心重点)

理解数据类型,必先搞懂 JS 内存划分,这也是赋值差异的根本原因。

1. 两大内存区域特点

计算机运行代码时,代码从硬盘(外存)加载到内存,内存主要分为栈内存堆内存

表格

内存区域 特点 存储内容
栈内存(Stack) 空间小、速度快、结构固定、自动回收 原始数据类型的值、引用类型的内存地址函数执行上下文也存放在栈中
堆内存(Heap) 空间大、速度慢、空间不固定、不会自动回收 引用类型(对象、数组)的真实数据

2. 核心规则

  1. 原始数据类型 :空间大小固定,直接存放在栈内存中。
  2. 引用数据类型 :真实数据存放在堆内存 ;栈内存中仅保存堆内存的地址(引用地址)
  3. 函数执行完毕后,栈内存会自动释放;堆内存需要 JS 垃圾回收机制回收,也可手动置空触发回收。

三、赋值机制:原始值拷贝 vs 引用值拷贝(代码实战)

根据内存存储规则,两种数据类型的赋值行为完全不同,也是日常开发最容易踩坑的点。

1. 原始类型:值拷贝(完全独立)

原始类型赋值是复制一份全新的值,两个变量互不干扰,修改其中一个不会影响另一个。

javascript

运行

javascript 复制代码
// null 属于原始类型
let a = null
let b = a  // 栈中拷贝值:b = null

b = 2      // 仅修改 b 栈内的值,和 a 无关
console.log(a) // null
console.log(b) // 2

原理ab 在栈内存是两个独立空间,赋值只是把值复制一份,相互隔离。

2. 引用类型:地址拷贝(共用同一堆数据)

对象、数组属于引用类型,赋值时不会拷贝堆里的真实数据 ,只会把栈中的内存地址 拷贝给新变量。多个变量指向堆中同一个数据,任意一个变量修改数据,所有关联变量都会受影响。

javascript

运行

bash 复制代码
let obj1 = { name: "谢鲁立" }
let obj2 = obj1  // 拷贝堆内存地址,obj1、obj2 指向同一个对象

obj2.company = "快手" // 通过地址修改堆中的真实数据
console.log(obj1, obj2)
// { name: '谢鲁立', company: '快手' } { name: '谢鲁立', company: '快手' }

原理obj1obj2 栈内地址相同,指向堆中同一个对象,一改全改。


四、null 与 undefined 深度解析(高频区分考点)

这两个类型都表示 "空",但语义、使用场景完全不同,下面结合代码逐一说明。

1. null 空值类型

语义

有意设置为空 ,表示此处本该有一个对象引用,但现在主动置空

  • 属于原始类型
  • 作用:清空对象引用、手动释放堆内存、标记 "无后续节点 / 数据"
典型使用场景
  1. 手动释放堆内存,辅助垃圾回收

javascript

运行

javascript 复制代码
// 超大数组,占用大量堆内存
let largeObject = {
  data: new Array(100000000).fill("xll")
}

largeObject = null; 
// 栈中地址置空,堆中大数据失去引用,会被垃圾回收
  1. 标记对象 / 链表无后续节点 经典链表场景:node.next 本应存下一个节点的引用,赋值 null 代表没有下一个节点

javascript

运行

ini 复制代码
node.next = null
  1. 主动定义 "空对象占位"

javascript

运行

javascript 复制代码
let obj = {
  name: '吴咸鸡',
  address: null // 主动设置:地址字段目前为空
}
console.log(obj.address) // null

2. undefined 未定义类型

语义

被动产生的空 ,表示变量 / 属性 / 返回值未初始化、不存在。属于原始类型,出现场景固定,一共 4 种:

场景 1:变量声明,但未赋值

javascript

运行

javascript 复制代码
let a // 只声明,不赋值
console.log(a) // undefined
场景 2:访问对象不存在的属性

javascript

运行

javascript 复制代码
let obj = {}
console.log(obj.name) // undefined
场景 3:访问数组不存在的索引

javascript

运行

ini 复制代码
let arr = [1, 2, 3]
console.log(arr[5]) // undefined
场景 4:函数无 return 返回值

函数没有手动写 return,默认返回 undefined

javascript

运行

javascript 复制代码
function notReturn() {
  // 无 return
}
console.log(notReturn()) // undefined

总结:null vs undefined

  • null人为主动设置的空(空对象引用)。
  • undefined代码运行时被动生成的空(未初始化、不存在)。

五、Number 数值类型:精度问题 & 大数溢出

JS 所有普通数字都属于 number 类型,底层统一使用二进制存储 ,由此带来两个经典问题:小数精度丢失超大整数溢出

1. 经典坑点:小数运算不精确

二进制无法精准表示部分十进制小数,导致运算结果异常:

javascript

运行

css 复制代码
let a = 0.1
let b = 0.2
console.log(a + b) 
// 输出:0.30000000000000004

原因:0.1、0.2 转二进制是无限循环小数,存储时被截断,造成精度丢失。

2. 超大整数溢出

number 类型有安全整数范围,超出范围会精度失真、科学计数法展示

javascript

运行

ini 复制代码
let num1 = 999999999999999999999999999999999999999999999999999999999999999
let num2 = 123456789098765433467324577654789008733233456899003466788924243
console.log(num1 + num2); 
// 输出:1.1234567890987655e+63(科学计数法,精度丢失)

六、BigInt 大整数类型(ES6+ 新增)

为解决 number 大数溢出问题,ES 新增 BigInt 类型,专门用来表示任意长度的大整数

使用规则

  1. 数字末尾加 n 即为 BigInt 类型;
  2. BigInt 和 Number 不能直接混合运算,会报错;
  3. 只能和同类型(BigInt)运算。

javascript

运行

javascript 复制代码
// 定义 BigInt:数字后加 n
let num3 = 999999999999999999999999999999999999999999999999999999999999999n
let num4 = 123456789098765433467324577654789008733233456899003466788924243n

console.log(num3 + num4, typeof num3); 
// 正常运算,typeof 结果为 bigint

// 报错:BigInt 不能和普通 Number 直接运算
// console.log(num3 + 1); 

// 正确:统一转为 BigInt
console.log(num3 + 1n)

七、Symbol 符号类型(ES6 新增)

核心特性

  1. 独一无二 :哪怕描述文本相同,两个 Symbol 也绝不相等;
  2. 属于原始数据类型
  3. 常用于对象私有属性、唯一标识符

代码演示

javascript

运行

javascript 复制代码
// 两个描述相同的 Symbol
console.log(Symbol("xll") === Symbol("xll")) // false

// 检测类型
console.log(typeof Symbol("xll")) // symbol

// Symbol 可以不传参数,代表绝对唯一
console.log(Symbol()) // Symbol()

实际应用:对象唯一键名

利用唯一性,给对象设置不会冲突的属性名

javascript

运行

csharp 复制代码
let obj = {
  [Symbol("xll")]: "谢鲁立", // Symbol 作为属性名
  prop: "1"
}

八、完整知识复盘(复习提纲)

1. 数据类型总览(8 种)

  • 原始类型(7 种):numberstringbooleannullundefinedSymbolBigInt
  • 引用类型(1 种):object(对象、数组、函数等)

2. 内存存储规则

  • 栈内存:存放原始值 、引用类型的地址;空间小、速度快、自动回收。
  • 堆内存:存放对象 / 数组真实数据;空间大、速度慢、依赖垃圾回收。

3. 赋值区别

  • 原始类型:值拷贝,变量相互独立。
  • 引用类型:地址拷贝,多变量指向同一堆数据,一改全改。

4. null & undefined 区分

  • null:主动置空,空对象引用,可用于释放内存。
  • undefined:被动产生,变量未赋值、属性不存在、函数无返回值。

5. Number / BigInt

  • number:二进制存储,存在小数精度丢失、大数溢出
  • BigInt:后缀加 n,支持超大整数,不能和普通数字混合运算。

6. Symbol

  • 天生唯一,适合做对象私有属性、唯一标识。

结尾

本文把 JS 数据类型、内存原理、赋值机制、常见坑点全部结合代码落地,日常复习可以对照代码逐行理解。这部分是 JS 根基,后续原型、作用域、闭包、深浅拷贝等知识点,都建立在栈 / 堆内存数据类型之上。

相关推荐
问心无愧05131 小时前
ctf show web入门157 158
前端·笔记
该用户已成仙1 小时前
vue3 使用 vuedraggable 报错 TypeError: isFunction2 is not a function
前端·javascript·vue.js
aidou13141 小时前
Kotlin中实现星级评价选择功能(仅支持整数)
前端·kotlin·自定义view·imageview·ontouchevent·customratingbar
良逍Ai出海1 小时前
我用 Codex 搭了一个 WordPress 独立站
前端
TPBoreas1 小时前
前端面试问题打把-场景题
开发语言·前端·javascript
问心无愧05131 小时前
ctf show web入门159
前端·笔记
恋猫de小郭1 小时前
Flutter 又为 AI 时代添砖加瓦:全新 ComponentLibrary 提议
android·前端·flutter
就叫_这个吧2 小时前
HTML或JSP页面链接CSS,link标签没问题,但不显示样式问题解决
java·前端·css·html·intellij-idea·jsp
IT_陈寒2 小时前
SpringBoot这个坑差点让我加班到天亮
前端·人工智能·后端