前端基础--内存与执行上下文

前端学习之路上的一些理解与总结 此文是在读过@这波能反杀 老师简书的前端基础进阶系列的一些自我理解与总结

内存


前端的内存空间有堆,栈,队列三种,要想能够对js中的函数调用,变量提示等一系列问题上能够更好更深的理解的话,就要对内存空间进行认识和理解,才能知道很多问题上的为什么。


  1. 堆数据结构是一种分散型的数据存储方式,堆数据空间是没有办法直接进行操作的,必须通过堆地址进行访问,引用,打个比方,好比你去图书馆,面前有有多的书,你知道书名,但是你不知道在哪里,去哪里找,那么你就可以通过索引号去查找这本书,同理当你把引用数据类型赋值给一个变量对象的时候,比如var a = {"name":"leslie"},那么这个a其实就是后面这个obj的引用地址

  2. 栈数据结构是一个先进后出的数据结构,先进入的在栈底,每次必须要等待栈顶执行完毕出栈后才能取到下一个数据,栈数据结构最典型的代表就是执行上下文调用栈
  3. 队列
    队列数据结构是一个先进先出的数据结构,,先进入的先执行,涉及到的例如js中的事件循环机制,就是利用队列的机制,陆续也会更新

分割,其实在js中所有的数据结构,无论是基本数据类型还是引用数据类型其实都可以看做存储在堆空间中,不同的是对于他们的赋值操作,如果是基本类型,比如

var a = 20;
//那么这个20就是基本数据类型,就会被复制传给a这个变量,a就拥有独立的一份数据
var b = a;
//给b赋值a,那么b则拥有了a数据的copy,那么a和b则是两个独立的变量,互相的操作都不会影响到彼此

而引用类型则是:
var tmp1 = {"name":"leslie"};
var tmp2 = tmp1;
//按照上文的说法tmp1存储的其实是对象的引用地址,而不是真的对象,因此将tmp1赋值给tmp2则是吧tmp1存储的引用地址赋值给tmp2,那么tmp2也拥有了指向同一obj的引用地址

tmp2.name = "not leslie";
//思考一下 如果执行这样的操作,会发生什么情况???

//首先会根据tmp2的引用地址找到堆空间的obj,然后修改堆空间obj的name属性,因此其他引用该对象的地方都会发生改变

执行上下文


执行上下文可以理解为函数执行的环境,每一个函数执行时,都会给对应的函数创建这样一个执行环境。

什么是执行上下文,就好比说你走在路上,进了一家店,在这家店里逛了一圈出来了,这家店就是你刚刚进入的一个环境,在js中,就是你遇到一个执行函数,然后你就进入这个函数的内部环境中,执行完了或者遇到了return语句后,你就从这个环境出来了。

什么时候会遇到执行上下文:

  • 全局环境:JavaScript代码运行起来会首先进入该环境
  • 函数环境:当函数被调用执行时,会进入当前函数中执行代码项目
  • eval(不建议使用,可忽略)

其中全局环境是最先进入的,因此他就会存在上下文调用栈的栈顶,然后遇到一个执行函数后,执行函数入栈,进入执行函数的上下文中,运行,直到运行完成或者遇到return语句,上下文结束出栈,然后继续寻找执行函数,另外全局环境只有在关闭页面的时候才会出栈。

用一个例子来说明:

console.log("1");

function fun1(){
    var tmp1 = "2"
    function fun2(){
        var tmp2 = "3"
    }
    return fun2;
}

var first = fun1();
first();

上面例子的执行上下文的入栈执行过程是:
全局上下文入栈 ---> fun1入栈 ---> fun1出栈 ---> first入栈 ---> first出栈 ---> 全局上下文出栈(关闭页面)

解释一下为什么是上面的调用顺序:

首先全局上下文入栈应该是毋庸置疑的,然后fun1是在哪个时候入栈的呢?是在声明的时候?还是在var first = fun1()的时候?

回头看我们的执行上下文的定义,每当一个函数执行的时候创造这样的一个执行环境叫执行上下文,因此fun1入栈的时候是在var first = fun1();的时候,然后遇到return fun2;执行结束,fun1出栈,然后fun2的引用地址赋值给first;遇到first(),first入栈,first执行完毕后first出栈,然后当页面关闭的时候,全局上下文出栈

你可能感兴趣的:(前端,内存,执行上下文)