写点什么

V8 数据存储(上篇):栈和堆

用户头像
梁龙先森
关注
发布于: 2021 年 05 月 27 日
V8数据存储(上篇):栈和堆

栈和堆,用于存储数据的两种方式。在深入理解 V8 中的栈和堆之前,我们先看看语言本身。

JavaScript 是什么语言?

通常将语言分为静态语言和动态语言,像 C 语言这类在使用前需明确定义变量的数据类型,我们称之为静态语言,相反的,像 JavaScript 在运行过程中需要检查数据类型的,称之为动态语言。


同样的在 JavaScript 使用过程中,编译器经常偷偷的进行类型转换,比如在 If() 条件语句中,"" 空字符串,会被转化为 false,我们把这种现象称之为:隐式转换。 能进行隐式转换的语言,我们称之为弱类型语言,相反的不支持隐式转换的语言成为强类型语言。


所以,可以看出:JavaScript 是动态的、弱类型语言

8 种数据类型

JavaScript 存在 8 种数据类型,其中 7 种为基础数据类型,1 种为引用类型,具体如下:

基础数据类型:

Boolean | Number | String | Symbol | BigInt | Null | undefined

引用类型:

Object


这里需要注意的是,typeof null === "object",这是历史遗留的 bug。区分不同类型的数据,是因为不同类型的数据存储的位置一样。


顺便提下,因为 Arraytypeof 值也是 object ,所以日常我们判断数组有下面的方式:

// 1Array.isArray([]).  // true
// 2Object.prototype.toString.call([]) === "[object Array]" // true
复制代码
栈和堆

一段代码经过编译,会产生一个执行上下文和可执行代码。在执行上下文中又分为变量环境和词法环境,变量环境用于存放当前上下文的变量,词法环境用于解决 JavaScript 中变量提升的问题,引入了块局作用域。以下面代码为例:


var a = 1let b = 2function c(){ console.log('')}
复制代码

上面代码经过编译后,var a 将被放到变量环境,并赋初值undefinedlet b,会被放到词法环境,注意此处并没有赋予初始值,倘若在未赋初始值便使用该变量,会形成一个暂时性死区,会报错。遇到function c 时,会将函数存储到堆中,同时将函数声明 c 放到变量环境,赋予函数在堆中的内存地址。


那这里为啥要将函数存在堆中,而不直接放在变量环境呢?

当代码开始执行后,会将当前代码编译后产生的执行上下文放入调用栈中,调用栈作为执行上下文切换的环境,当栈数据量越大,上下文数据销毁、切换需要消耗大量时间,会影响到整个程序的运行效率,因此栈空间一般都不大。也因为栈空间不大,当你疯狂递归执行某块代码,容易造成栈空间溢出。


堆空间用于存储引用类型,比如大对象,函数等等,会在分配存储空间、以及取数据存在一定的开销。


通过存储整个过程,我们可以得知,存在 3 中存储类型:栈、堆,以及代码空间。栈用于存储简单的基本数据类型,堆存储引用类型这些潜在的大数据对象。


涉及到堆和栈的数据存储,必然存在数据回收,也就是浏览器的垃圾回收机制。后面再讲!

发布于: 2021 年 05 月 27 日阅读数: 17
用户头像

梁龙先森

关注

无情的写作机器 2018.03.17 加入

vite原理/微前端/性能监控方案...,正在来的路上... 最近太忙...

评论

发布
暂无评论
V8数据存储(上篇):栈和堆