1

内存的分配(示意)

启动程序,就需要分配内存给运行的程序。启动浏览器,就会分配一定内存供浏览器使用,浏览器在会分配相应的内存供诸如HTML+CSS,JS,'HTTP','其他插件、定时器`等模块使用,如下图。
内存的分配

会有一部分内存供JS模块使用,JS一般会将JS代码存储在代码区,数据区内,通过某种联系将代码和数据对应在一起,如下图。
内存的存储

内存图

示意图

内存图就是简化模拟示意JS使用的内存中的数据区中的情况,简单的分为栈内存Stack,堆内存Heap,如下图。明显,左边是原始代码,中间是栈内存,右边是堆内存
内存图

使用

左边原始代码定义一个变量,在栈内存中就会用64位存储一个值。如果原始代码中变量是非对象栈内存中这个值就是直接值堆内存没有数据。如果原始代码中变量是对象栈内存中就会存储堆内存的地址(随机),堆内存中会存储这个对象的所有内容
内存图使用_1_1

看到上个图,原始代码区里最后一行O2=O,将一个对象赋值给另一个变量时,实际上是将堆内存的地址赋值给另一个变量,转换如下图,O2在栈内存中的内容就变成了和O一样的堆内存地址
内存图使用_1_2

应用实例

第一个

  • 原始代码中定义变量a=1,Stack中存储1
  • 原始代码中定义变量b=a,Stack中存储b的值和a一样,为1
  • 原始代码中赋值b=2,都是非对象,Stack中直接将b的值改为2,不影响a
  • 全程非对象,所以没有涉及堆内存Heap

数据类型面试题_1

第二个

  • 原始代码中定义变量a={name:'a'},是个对象,随机分配Heap地址(比如:31)并在Heap中存储这个对象,在Stack中存储这个Heap地址,比如ADDR 31
  • 原始代码中定义变量b=a,是个存在的对象,将a的Stack值(ADDR 31)(Heap地址)赋给b的Stack值
  • 原始代码中赋值b=null,赋给了b一个非对象,将b的Stack值改为null,不影响a
  • 全程操作Stack值,对象的Stack值为Heap地址

数据类型面试题_2

第三个

  • 原始代码定义变量a={n:1},随机分配Heap地址(比如:34)并在Heap中存储这个对象,在Stack中存储这个Heap地址,比如ADDR 34
  • 原始代码中定义变量b=a,是个存在的对象,将a的Stack值(ADDR 34)(Heap地址)赋给b的Stack值
  • a.x=a={n:2},这句话阅读顺序从左往右。首先,在Heap 34中添加新属性x:a,现在a的值是ADDR 34,所以新属性相当于x:ADDR 34。然后,把{n:2}赋值给a,因为是个新对象,所以重新分配Heap地址(ADDR 54),并把a的Stack值变更为新的Heap地址(ADDR 51)。
  • alert(a.x),现在a的值实际是ADDR 54ADDR 54里面是没有x这个属性的,所以返回undefined
  • alert(b.x),b一直是ADDR 34,其中x属性值为ADDR 54,所以是个对象,返回[object Object]
  • 总之就是,原始代码里对对象的操作都在堆内存Heap中实现,对变量的操作都在栈内存Stack中实现。非对象的Stack值就是直接值,对象的Stack值是堆内存Heap的地址

数据类型面试题_3

第四个

  • 原始代码中定义变量a={name:'a'},Heap中存储对象,Stack中存储Heap地址(ADDR 101)
  • 原始代码b=a,把a的Stack值(Heap地址)赋给b的Stack值
  • 原始代码b={'name':'b'},赋给b一个新对象,Heap中存储新对象,b的Stack值变更为新的Heap地址(ADDR 301)
  • 所以,a.name没有变,还是a

数据类型面试题_4

第五个

  • 原始代码中定义变量a={name:'a'},Heap中存储对象,Stack中存储Heap地址(ADDR 51)
  • 原始代码b=a,把a的Stack值(Heap地址)赋给b的Stack值
  • 原始代码设置b.name=b,就是ADDR 51中的name值变更为b
  • 所以,a.name也就是ADDR 51中的name值,等于b
  • 这里,a和b的Stack值都指向同一Heap地址ADDR 51,所以无论对那个进行操作,都是对一个东西做操作,所以会互相影响

数据类型面试题_5


BreezingSummer
45 声望0 粉丝