电脑内存分为虚拟内存和物理内存,代码运行都是在虚拟内存中去执行的。
let a = {n:1}
let b = a
a.x = a = {n:2}
console.log(a.x)
console.log(b)
首先浏览器在执行以上代码的时候,首先会从计算机的虚拟内存中分配两块内存:堆、栈
- 栈 Stack(ECStack]):作用主要是有两个:供代码执行、存储声明的变量和原始值类型的数据
- 堆 Heap:作用只有一个存储对象类型的值
默认在堆内存中,开辟一个空间地址为16进制的空间称为全局对象GO(Global Object),全局对象默认存储的是浏览器为JS提供的内置API,例如 setTimeout\setInterval\requestAnimation
接下来会执行JS代码
首先会在栈内存中产生一个全局的执行上下文(ECG),供全局代码执行的环境。 在代码的执行过程中会声明变量,所以需要一个存放变量的地方:变量对象 VO/AO。
首先执行的是 let a = {n:1}
- 先创建值:值是一个对象,则会在堆中开辟一块空间(假如为 0x001)
- 再将a放在VO中存储
- 最后让VO中的变量与值关联。a指向0x001
图示如下:
执行第二句: let b = a;
- 创建值,这里因为值就是a,所以值就是 0x001
- 将b放在VO中存储
- 关联
执行第3句:a.x = a = {n:2}
在JS中,连续赋值的时候,正常情况下是从右往左处理,例如 let a = b = 1, 先执行 b = 1,再执行let a = b,但是如果遇到成员访问则优先级更高则先执行。所以第三句的执行顺序是:
- 还是先创建值,在堆中创建对象 {n:2} 0x002
- 成员访问优先级更高,执行 a.x = 0x002
- 再执行a = 0x002
所以打印答案也就一目了然了
a.x -> undefined
b -> {n:1,x:{n:2}}