JavaScript中数据是如何存储的

45 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第36天,点击查看活动详情

数据是如何存储的

我们先看两段代码:

function foo(){
  var a = 1
  var b = a
  a = 2
  console.log(a) // 2
  console.log(b) // 1
}
foo()
function foo(){
  var a = {name:"LiMei"}
  var b = a
  a.name = "LiLei" 
  console.log(a) // {name:"LiLei"}
  console.log(b) // {name:"LiLei"}
}
foo()

在第一段代码中,给变量a重新赋值时,变量b的值没有被改变。两者相互是没有影响的。再看第二段代码,给对象a的属性name重新赋值,变量b对象的属性name的值也被改变了。

其实对比我们也能发现,之所以会出现这样的差异,肯定与数据类型有关了,代码一种变量类型都是数字,而代码二中变量都是对象。从数据类型的划分来说,数字属于基本数据类型,而对象属于引用数据类型。

语言特性

从语言类型内部来分的话,JavaScript可以划分为上面说的基本数据类型和引用数据类型。但如果从各语言通用特性来分,我们一般也有两个维度:

  • 强/弱类型
  • 动态/静态类型
强/弱类型

强弱类型主要指的是能否可以隐式转换。举个例子:

let a = 1
a = true
console.log(a) // true

第一行代码中变量是数字类型,也可以给它赋值成布尔型,在解释器在检测到赋值类型变了以后,会隐式改变变量的所属类型。

像java就是强类型的,赋值过程中出现类型不同就会报错。

动态/静态类型

动态/静态过程,我们一般的说法是静态编译,动态运行。这里的意思也类似,在编译过程中就需要确定变量类型的语言就称为静态类型语言;相反,可以在运行过程中动态改变变量类型的语言就是动态类型语言。JavaScript就是动态类型语言。

image.png

内存空间

我们要想知道JavaScript数据是如何存储的,先要清楚存储的空间种类。

image.png

存储空间大体分代码空间、栈空间和堆空间。代码空间主要存储的执行的代码语句。后面再说。现在主要围绕本篇开头的代码来讲解栈空间和堆空间。

我们再来看一段代码:

function foo(){
  var a = "juejin"
  var b = a
  var c = {name:"juejin"}
  var d = c
}
foo()

这里面变量既有基本类型,也有引用类型。

栈就是我们之前说的调用栈,用于存储上下文。当执行到变量a和b时,会放入变量环境中;再执行到变量c和d,情况就不同了,c和d是引用类型,变量仍是存储于变量环境中,但它的值并不是对象本身,而是对象在另一个地方的存储地址,那个存储的地方就是堆。这也就解释了开篇为什么对象改变属性值同时会改变其他对象的属性值,因为它们都指向同一个堆地址,里面值是同时被改变了的。

那为什么不能把引用类型的值直接存放于栈中,非要搞个堆出来呢?

那是因为一般栈空间不会设置很大,它要用于上下文的高效切换。而相对来说,堆空间就比较大,所以存放引用类型的具体值。