今天聊一下JavaScript中的堆栈溢出
一、什么是堆栈溢出?
每次执行JavaScript代码时,都会分配一定尺寸的栈空间(Windows系统中为1M),每次方法调用时都会在栈里储存一定信息(如参数、局部变量、返回值等等),这些信息再少也会占用一定空间,如果存在较多的此类空间,就会超过线程的栈空间了。
说白了就是就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了别的数据。
二、引起的原因是什么?
function isEven (num) {
if (num == 0) return true;
if (num == 1) return false;
return isEven(Math.abs(num) - 2);
}
console.log(isEven(1000000000000)); //output Uncaught RangeError: Maximum call stack size exceeded
由于过多的函数调用,导致调用堆栈无法容纳这些调用的返回地址,一般在递归中产生。堆栈溢出很可能由无限递归(Infinite recursion)产生,但也可能仅仅是过多的堆栈层级。
三、怎么解决呢
1、使用setTimeout()来解决(推荐)
function callback(f) {
f();
}
function foo() {
foo(); //执行1000次左右会发生堆栈溢出的错误,
//setTimeout(foo, 0); //永远不会堆栈溢出
}
foo()
2、使用闭包解决
function isEven(num){
function isEvenInner(num){
if(num === 0){return true;}
if(num === 1){return false;}
return function(){
return isEvenInner(Math.abs(num)-2);
}
}
function simplify(func,num){
var value=func(num);
while(typeof value == 'function'){
value=value();
}
return value;
}
return simplify.bind(null,isEvenInner)(num)
}
console.log(isEven(100000));//num太大会导致浏览器卡顿
3、使用尾调用(这个方法还不是很了解,想深入了解的朋友可以自寻资料)
后续会继续更新~