JavaScript类型详细讲解:从内存到相等性判断

0 阅读4分钟
一文带你搞懂原始类型和引用类型(复杂类型),V8的内存机制,以及==和===的“爱恨情仇”。

本文将从类型分类讲起,带你走进V8的调用栈和堆调用,最后彻底搞清 == 和 === 的区别。读完这篇文章,你在写代码时将会更加有底。

一.JavaScript的两大类类型

JS中的数据类型分为基本类型引用类型

1.基本类型

主要分为七种:string、number、boolean、undefined、null、bigint、symbol。

它们的特点:

  • 存储在栈内存中
  • 直接保存值,赋值时是“值拷贝”
  • 不可变:无法修改初始值,只能重新赋值
var a = 1;
var b = a;//b得到了a相同的值
b = 2;
console.log(a);//1,a的初始值并没有改变

引用类型(复杂类型)

包括Arrar、Object、Function、Date。

它们的特点是:

  • 存储在堆内存中
  • 变量保存的是内存地址(引用),赋值时拷贝的是引用
  • 可变:通过引用修改对象的内容,所有指向该对象的内容都会发生变化。
let obj = { name : '张三'};
let obj2 = obj;
obj2.name = '李四'console.log(obj.name);//

二.V8引擎执行过程:栈和堆的完美协作

V8是Chorme和Node.js背后的JS引擎,它的执行过程大致如下:

1.创建调用栈

调用栈是一个栈结构,用来存放预编译的过程,管理函数调用和代码执行顺序。每个函数执行时都会创建一个执行上下文,并被压入栈顶。

调用栈1.jpeg

2.执行上下文的创建

V8开始执行代码时首先创建全局执行上下文,其中包含:

  • 变量环境:记录变量和函数声明
  • 词法环境

3.栈中存值,堆中存对象

在代码执行过程中,V8对不同数据的处理方式不同:

  • 原始类型的值:直接存储在调用栈的当前执行上下文中。因为原始值的大小固定并且占用的内存小,放入栈内存中可以快速访问。
  • 引用类型的值:对象、数组等实际数据存储在堆内存中,V8会在堆中分配一块空间,然后把这个空间的引用地址指针)压入栈中。

屏幕截图 2026-05-16 130658.png

那么为什么要这样设计呢?

  • 栈内存:容量小、存取速度快
  • 堆内存:容量大、速度慢、效率低
  • 将大体积的对象放入堆中,保证了栈不用设计很大从而影响 V8 的执行效率,也不会发生爆栈。

三.补充知识:==与===的区别了解

很多代码中隐藏的bug都源于混淆这两个运算符。它们的本质区别:==会偷偷的进行类型转换,而===不会进行类型转换

1.严格相等 ===

  • 比较两个值的类型是否相同值是否相同
  • 类型不同直接返回false
  • 不会进行任何转换

2.抽象相等 ==

  • 如果两个值类型相同则与===比较结果一致
  • 如果类型不同,会进行类型转换,再进行值的比较

== 的转换规则:

类型组合转换方式
number vs string将字符串转换为数字,然后比较
boolean vs 任何类型将true->1,fales->0,再转换为数字进行比较

建议:除了一些极少数的场景,日常编码中最好都使用===,避免发生一些错误转换bug。

四.总结

  • JavaScript中的类型分为7种基本类型(存在栈中)和一些引用类型(堆中存储实体,栈中存放地址)
  • V8引擎通过调用栈堆内存的分离设计,保证了执行效率并且避免了爆栈
  • ==会进行类型转换,规则复杂且容易出错;===不会进行类型转换,比较严格并且安全

清楚了解了类型和它们的存储方式,可以帮助你写出更加高效可靠的代码。

类型是JavaScript的基石,V8的执行机制规则让你知其然更知其所以然。希望这篇文章能帮助你彻底打通类型和底层存储的任通二脉。