堆和栈
堆内存
每当定义一个变量、常量或者对象的时候,都会有一个存储这些值的地方,这个地方就是内存堆;
可用的内存是有限的,因此合理的使用内存是非常有必要的,像 c 语言是通过显示的分配和释放来合理的利用内存的;javascript 是通过垃圾回收机制来合理的处理内存的;
v8引擎中,垃圾回收器的名字叫做:Orinoco
标记和清除算法
这一算法的工作方式是将对象标记为可获得或者不可获得,并将不可获得的对象给清除掉;
垃圾回收器周期性的从根部或者全局对象开始,移向被他们引用的对象,接着再移向被这些对象引用的对象,以此类推,所有不可获得的对象会在之后被清除
内存泄漏
虽然垃圾回收器的效率很高,但是单凭一个算法并不能很好的去管理内存;
经常容易出现内存泄漏的地方:
1):全局变量:如果不断的去创建全局变量,不管这些变量有没有被应用,他们都是存在的,在程序的整个执行过程中,他们都会滞留在某一个空间内,如果这些变量是嵌套多层的对象,那么久会占用和浪费更多的内存;
2):事件监听器:在一个页面中,我们可以回由于一些动画效果等需求,使用到大量的监听器,监听一个事件的触发,然后去实现一些效果,但是在用户离开这个页面的时候这些监听器并没有被移除掉,那么这个也是会造成内存的泄漏的;
3):intervals 和 timeout:在使用定时器或者延时器的时候,我们经常会和必报一起使用,比如说去抖和节流使用的时候,在我们使用闭包的时候,有时候回去定义一些变量,但是我们在处理的时候经常会只是去清除了一下 intervals 或者 timeout 并没有是清除这个闭包,这样的话,没有清除闭包,那么这些变量就也没有被清除掉,其实这还是造成大量的变量引起的内存泄漏问题;
4):DOM的清除和操作:我们在使用DOM 去进行一些操作的时候,有时候为了性能的考虑,我们会用一个变量去赋值这个DOM,这样从另一方面,也是变量定义的一个过程,这样这个变量就一直的存在了;
调用栈
栈是一种遵循LIFO(先进后出)的规则的数据结构,用于存储和获取数据;javascript 引擎通过栈来记住一个函数中最后执行的语句所在的位置
例如: function multify(x) { return x * 2}
fucntion calSun() { const sum = 4 + 2 ; return multify(sum) }
calSum()
1):引擎发现代码中的两个方法函数;
2):运行 calSum() ;
3):将 calSum() 压栈,并执行 sum 和的计算;
4):运行 multify() ;
5):将 multify 压栈,并执行 x * 2;
6):在返回结果时,将 multify 从栈中弹出,然后回到 calSum() ;
7):在 calSum 返回结果的时候,将calSum 从栈中弹出,然后继续执行后面的代码
栈溢出
在不对栈执行弹出的情况下,可连续压栈的数目取决于栈的大小,如果超过了这个界限还不断的压栈,最终会导致栈溢出; chrome 浏览器将会抛出一个错误以及被称为栈帧的栈快照。