堆栈内存
JS代码之所以能够在浏览器运行,是因为浏览器会从计算机的内存挑中分配出对应的内存,用来存储值和运行代码
内存有两种:
- Stack:栈内存 ECStack(Execution [ˌeksɪˈkjuːʃn] Context Stack),存储的值有两种:
+原始值类型存储在栈内存中
+提供对应的执行上下文 EC(Execution Context)供代码执行 - Heap:堆内存
+存储对象类型的值
下边通过一段代码来具体了解一下:
var a = {
n: 1
};
var b = a;
a.x = a = {
n: 2
};
console.log(a.x);
console.log(b);
这段代码是如何运行的呢?

文字版
-
浏览器开辟堆内存和栈内存
-
堆内存中分配出一块空间(假设有个16进制地址0X000),存储内置的API:
setInterval,setTimeout,JSON,requestAnimationFrame, open....等,
我们把这块空间叫做GO(global object):全局对象 -
为了区分是全局代码执行,还是函数代码执行,或者块级上下文执行,所以会进行区分
这里是全局代码执行所以会形成EC(G):全局执行上下文(全局代码都会在这里执行) -
形成全局上下文之后,代码进栈执行(执行完会出栈释放掉,不释放的话就会形成闭包)
-
在全局执行上下文中,会有一个空间叫VO(G):全局变量对象,存储全局上下文中声明的变量
+特殊性:在新版本当中,在全局执行上下文中,【基于let/const声明的变量存放在这里,基于var/function声明的变量是直接存储到GO中的】
-
怎么访问GO中的东西呢?是因为浏览器会默认在全局执行上下文中声明一个变量叫:window,window指向GO的存储地址:0X000
-
代码执行(当然代码执行之前还要做好多事,比如说:词法分析,变量提升,作用域链等,以后再补充)
-
代码执行过程中,遇到变量等于什么的时候都是:
@1.先创建值
@2.声明变量 declare
@3. 变量和值关联 defined -
全局上下文中使用变量
@1. 先看VO(G)中是否有
@2 再看GO中是否有
@3 如果都没有,则报错:变量为北定义 -
如果是连等赋值:var a = b = 10,正常顺序都是从右到左:
@1. 创建值10(存储再栈中)
@2. b = 10
@3. var a = 10
但是遇到优先级较高的,则先执行优先级高的操作(例如一开头的代码中:a.x = a = {...}, .是成员访问,优先级高于=) -
执行:
var a = {
n: 1
};
var b = a;
a.x = a = {
n: 2
};
console.log(a.x);
console.log(b);
var a = {
n: 1
};
@1: 堆内存中开辟一块空间:0X001
存储:n:1
@2: var 一个变量a,存储在GO中
@3: a和0X0001关联
a = {n:1}
var b = a;
@4: var b=a :将b指向a的内存地址:0X001
b={n:1}
a.x = a = {
n: 2
};
@5: 堆内存再开辟一块空间:0X002
存储:n:2
@6: a.x 地址指向 0X002(.优先级高于=),所以a (地址:0X001)为
{
n:1,
x: {
n:2
}
}
b和a指向的是同一个地址:0X001,所以b也是:
{
n:1,
x: {
n:2
}
}
@7: a={n:2} a的地址指向0X002
console.log(a.x); // a={n:2} 并没有变量x,所以输出值是:undefined
console.log(b); // console.log(b):b地址指向0X001,所以输出:{n:1,x:{n:2}}
栈结构
以后再补充
网友评论