在 JavaScript 中,您会听到两个概念:堆栈溢出和内存泄漏。这两种机制在开发中很少遇到,但是一旦遇到就很头疼。先说说两者的概念,触发原因和解决方案。
什么是堆栈溢出?我们知道JS中的数据存储分为栈和堆。程序代码需要一定的存储空间进行计算,也就是栈。栈遵循先进后出的原则,所以程序从栈底开始运行计算,调用程序的内部函数。而return会不断的进行入栈和出栈操作,栈中占用的资源也在不断的相应变化着,但是一旦调用,出栈操作太多了,return就是没有足够的出栈。这时候,会造成栈满,然后栈溢出。打个比方:这就像和女朋友去吃火锅,点了一只鸳鸯火锅。他们两个开始吃辣一个,另一个不吃辣。很和谐。结果,你贪吃,把很多菜放在了辣的一边。不能再吃了,辣油溢出到不辣的一边,那你女朋友就不开心了,到头来肯定会被骂的。当然,JS栈溢出后,他不会骂你,但会报错,继续罢工。我们来看一个网上使用比较多的模拟代码(递归)的例子:
function isEven(n) {
if (n === 0) {
return true;
}
if (n === 1) {
return false;
}
return isEven(Math.abs(n) - 2);
}当我们打印console.log(factorial(10))时,答案为true,结果运行速度更快,而当我们输入console.log(factorial(10000000))时,结果是错误的: Uncaught RangeError: Maximum call stack size exceeded(这个在谷歌浏览器测试中运行),这个错误的意思是:最大调用超过了栈大小,这是为什么?原因是程序需要在执行代码的过程空间就是栈,一般大小在1M左右,每次调用程序中的函数,这些都会占用一定的空检查,占用太多就会超过程序分配的栈空间。会报错。那么,如何解决这个问题呢?以上面的递归为例,解决方案如下(我们前面提到了闭包,这里我们使用闭包和Trampoline(蹦床原理)来解决):
function isEven(n) {
function isEvenInner(n) {
if (n === 0) {
return true;
}
if (n === 1) {
return false;
}
return function () {
return isEvenInner(Math.abs(n) - 2);
}
}
function trampoline(func, arg) {
var value = func(arg);
while (typeof value === "function") {
value = value();
}
return value;
}
return trampoline.bind(null, isEvenInner)(n);
}什么是内存泄漏?内存泄漏是指程序分配的堆栈中的一块内存既不能使用也不能回收。意思是你和你女朋友在吃火锅,中间没有汤,所以不能烫。内存泄漏一般有以下几种原因:
function func() {
a = 1;
}setInterval(function () {
console.log(1)
}, 1000);var elements = {
button: document.getElementById(button),
};
function doStuff() {
button.click();
}
function removeButton() {
document.body.removeChild(document.getElementById(button)); // 这时,我们仍然有一个引用指向全局中的elements。button这个节点仍在内存中,不会被回收。
}function my(name) {
function sayName() {
console.log(name)
}
return sayName
}
var sayHi= my("tom")
sayHi() //tom在函数 my() 内部创建的 sayName() 函数不会被回收机制回收。如果不调用闭包,由于闭包将携带包含它的函数的作用域,因此它会比其他函数占用更多。更多的内存。过度使用闭包可能会导致过多的内存使用。
最后,再添加一个概念。我们一直都提到程序在运行时占用的内存空间,而程序在运行的时候,就是不断的push和pop,调用和销毁。这涉及到浏览器的垃圾收集机制。什么是垃圾?垃圾是一个不再使用的变量。顾名思义,您的变量是无用的。抱歉,您将被浏览器破坏以腾出空间。浏览器常用的垃圾回收方式有两种:标记移除和引用计数。

去除标记p>
这是最常用的方法。当一个变量进入执行时,会给出一个前面的标记,证明该变量已经进入了代码的执行环境。当变量被执行并离开执行环境时,它会被标记为离开执行环境。这时候垃圾回收器会清除环境中的变量以及环境中变量所引用的标签。在此之后标记的变量将被视为要删除的变量,因为环境中的变量无法再访问这些变量。最后。垃圾收集器完成内存清理工作,销毁那些标记的值,并回收它们占用的内存空间。
引用计数
这个方法用的不多。引用计数,顾名思义,就是统计这个变量被引用的次数。当一个变量被声明并赋值为引用类型时,该变量的引用次数将增加1,如果包含该值的引用变量附加了另一个值,则该值的引用次数将减少1 . 当引用数变为 0 时,无法访问该值。当垃圾收集器运行时,它会回收0引用值占用的内存并释放内存。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-380808-1.html
生产加工和运输流程啊