web前端高级JavaScript - 数据类型区别和堆栈内存处理

栈内存(stack) & 堆内存(Heap)

本节将根据几道题来讲述:js代码在浏览器中运行的底层原理以及栈内存和堆内存

  • 涉及名词:
  • declare & define
  • ECStack(Execution Context Stack) 和 EC(Execution Context)/EC(G)全局执行上下文,用于执行代码
  • GO(Global Object)全局对象:它是一个堆内存,存储的都是浏览器内置的API属性方法,在浏览器端让window指向它
  • VO(Variable Object)(G)全局变量对象:全局上下文中用来存储全局变量的空间,它不是GO,但有时候某些情况下VO(G)中的东西会和GO中的东西有所关联
  • 接下来我们由几道题开始
//------------1-------------------
var a = 12;
var b = a;
b = 13;
console.log(a)
//-------------2------------------
var a = {n: 12};
var b = a;
b['n'] = 13;
console.log(a.n);
//--------------3-----------------
var a = {n: 12};
var b = a;
b = {n: 13};
console.log(a.n);

上面几题并不难,相信大家都能得到正确答案,那么抛开题目本身和答案,这么简单的一段代码在浏览器中运行的底层原理是什么呢,接下来我们来逐个分析

  • 第一题运行原理剖析(值类型)
  1. 浏览器为了运行js代码:首先它会在计算机的内存(我们常说的内存条)中分配出一块内存,用来供代码执行,就是所谓的栈内存(Stack),专业一点的我们把它叫执行环境栈即ECStack(Execution Context Stack)
  2. 在总的执行环境栈(ECStack)中又分为多个不同的区域,为了区分是哪个区域(全局或函数等)下的代码执行,会产生一个“执行上下文”EC(Execution Context)。比如全局执行上下文,函数执行上下文等,每个执行上下文都是一块单独的不同的区域
  3. 上面的代码中没有函数,所以在执行时肯定会先产生一个全局的执行上下文EC(G) =>Execution Context(global),在全局代码的执行过程中会创建变量a和变量b,这些变量也得需要保存起来。这时就会产生一个叫变量对象的东西VO/VO(G)=>Variable Object (Global),用来存储当前上下文声明的变量
  4. 因为代码需要在栈中执行(第一步中的执行环境栈),所以会有个进栈执行的过程,然后执行完出栈
  5. 进栈执行开始创建变量,创建变量会有如下几个步骤:var 变量 = 值
    • 先创建值,基本类型值直接存在栈内存中,引用类型值则都会开辟一块单独的内存空间(堆内存Heap)用来存储信息
    • 声明变量并存放到当前上下文的变量对象中(VO/AO)
    • 让变量和值关联到一起,也就是所谓的赋值操作,此操作叫做定义defined
  6. 根据上一步原理,先创建一个值12,然后再创建一个变量a,最后让变量a与值12关联。接着创建b变量,因为b指向的是变量a,所以变量b也会与12关联。再继续往下执行,又创建一个值13然后让b重新与13关联,最后得到:a依然与12关联,而b则与新值13关联
  7. 输出a的结果12

一图解真相
在这里插入图片描述

  • 第二题原理剖析(引用类型)

前4步与第一题相同

  • 从第5步开始,因为涉及到引用类型,所以这里会重新开辟一块单独的内存(堆内存),用来存储对象信息。堆内存的创建过程:
  1. 在计算机内存中分配一个单独的内存(堆内存)
  2. 生成一个16进制的地址
  3. 把对象中的键值对分别存储到堆内存中
  4. 把堆内存的地址放置到栈内存中,供变量使用
  5. 变量与堆内存地址关联
  • 第6步中先开辟一块堆内存,存储对象信息{n:12},然后让变量a与堆内存的地址关联。执行var b = a;因为b指向的是a变量,所以b也会与堆内存的地址关联。接着b[‘n’] = 13; 通过对象成员访问的方式将堆内存中的成员n的值改为13(因为b也是指向的这个堆)
  • 最后a.n的值也变为13,因为a和b都是同一个堆内存地址,指向的都是同一个堆。

一图解真相
在这里插入图片描述

  • 第三题原理剖析
  • 前5步同上一题
  • 第6步:从var b = a;之前的代码都是一样的。不同的是当执行到b={n: 13}时,发现是一个新的对象,这时就会重新开辟一个新的堆内存用来存储n: 13,同时生成一个新的内存地址,然后让b与新的堆内存地址关联,而a不变依然与原来的堆内存地址关联,所以b.n会变为13,而a.n依然是12
    最后输出12

一图解真相
在这里插入图片描述

  • GO(global object)

在上面的讲述中我们已经学习了EC(G)、ECStack’、VO(G),那么还有个名称叫做GO(全局对象),注意这里是 全局对象 , 而不是 全局变量对象
GO是在加载页面时默认就生成的东西,而在这个对象中主要用来存储浏览器供JS调用的一些属性和方法,如setTimeOut、setInterval…
它会在全局执行上下文的全局变量对象(VO(G))中默认创建一个window变量,window指向GO,window代表的就是全局对象。

  • 思考题
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x);
console.log(b);
```
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值