JS堆栈溢出、内存泄漏、垃圾回收小笔记,整

您所在的位置:网站首页 js内存溢出和内存泄漏的区别在哪 JS堆栈溢出、内存泄漏、垃圾回收小笔记,整

JS堆栈溢出、内存泄漏、垃圾回收小笔记,整

2024-06-20 03:02| 来源: 网络整理| 查看: 265

堆栈溢出

什么是堆栈溢出?我们知道JS中的数据存储分为栈和堆,程序代码运行都需要一定的计算存储空间,就是栈了,栈遵循先进后出的原则,所以程序从栈底开始运行计算,程序内部函数的调用以及返回会不停的执行进栈和出栈的操作(递归),栈内被所占的资源也在不断的对应变化,但是一旦你的调用即进栈操作过多,返回即出栈不够,这时候就会导致栈满了,再进栈的就会溢出来。

用代码举例;

function isEven(n) {    if (n === 0) {        return true;   }    if (n === 1) {        return false;   }    return isEven(Math.abs(n) - 2); } //1.console.log(factorial(10))   true   运行比较快 //2.console.log(factorial(10000000))   Uncaught RangeError: Maximum call stack size exceeded //错误是 最大调用超过堆栈大小

递归层多了就报错,这是为什么呢?原因就是,程序在执行代码过程中,需要一定的计算空间即栈,一般大小为1M左右,当你每次调用程序内的函数等其它时,这些就会占用一定的空检,当占用过多时,就会超过该程序所分配的栈的空间,就会报错了。那么,如何解决这个问题?就拿上面的递归例子来说,解决办法如下(前文我们提到了闭包,这里就用闭包来解决):

function isEven (num) {    if (num === 0) {        return true;   }    if (num === 1) {        return false;   }    return function() {        return isEven(Math.abs(num) - 2);   } } //Outputs: true console.log(isEven(4)()()); ​ //此时每次调用时,返回一个匿名函数,匿名函数执行相关的参数和局部变量将会释放,不会额外增加堆栈大小。 //个人理解,新出来一层,然后外层的就销毁了,因为最外层的isEven已经销毁了 内存泄漏

什么是内存泄漏?内存泄漏是指程序被分配的栈内有一块内存既不能使用,也不能被回收。 (此处可以联系强引用弱引用知识点、Map和Object的区别知识点)

导致内存泄露的情况:

//1.********************************************* //【函数内未使用声明变量关键字的变量[意外的全局变量]】 //全局变量的生命周期最长,直到页面关闭前,它都存活着,所以全局变量上的内存一直都不会被回收。 function func() {    a = 1; } //2.********************************************* //【未销毁的定时器,要记得clearTimeout()】 //setTimeout 和 setInterval 是由浏览器专门线程来维护它的生命周期。 //所以当在某个页面使用了定时器,当该页面销毁时,没有手动去释放清理这些定时器的话,那么这些定时器还是存活着的。 setInterval(function () {    console.log(1) }, 1000); //3.********************************************* //【DOM以外的节点引用】 //DOM 元素的生命周期正常是取决于是否挂载在 DOM 树上,当从 DOM 树上移除时,也就可以被销毁回收了 //但如果某个 DOM 元素,在 js 中也持有它的引用时,那么它的生命周期就由 js 和是否在 DOM 树上两者决定了 //记得移除时,两个地方都需要去清理才能正常回收它。 var elements = {    button: document.getElementById('button'), }; function doStuff() {    button.click(); } function removeButton() {    document.body.removeChild(document.getElementById('button'));    // 这时,我们仍然有一个引用指向全局中的elements。button这个节点仍在内存中,不会被回收。 } //4.********************************************* //【闭包的循环引用】 function my(name) {    function sayName() {        console.log(name)   }    return sayName } //在函数my()内部创建的sayName()函数是不会被回收机制回收 //如果闭包不被调用,由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多。 var sayHi= my("tom") sayHi() //tom //5.********************************************* //【网络回调】 //某些场景中,在某个页面发起网络请求,并注册一个回调,且回调函数内持有该页面某些内容。 //那么,当该页面销毁时,应该注销网络的回调,否则,因为网络持有页面部分内容,也会导致页面部分内容无法被回收。 垃圾回收

垃圾回收机制,清除孤儿 语言当中一般分两种,一种是自动清理,一种是手动清理(GC),js中只有自动清理

垃圾回收机制就是将引用对中的地址的对象设置为null,并且将所有引用该地址的对象都设置为null,并且移除事件侦听

不会即时清除,垃圾回收车会根据内存的情况在适当的时候进行清除堆中的对象 内存到达一定程度了才会进行回收

var obj={        a:1,        b:2   }; var obj1=obj; obj=null; obj1=null;    // 必须将所有引用的对象全部设为null 堆里面才会变成孤儿,要不然无法回收 ​

讲这个的好文章

另一篇



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3