您好,我正在处理此函数的问题,导致最大调用堆栈超出错误。该函数不是递归的,所以我真的不明白为什么它超出了调用堆栈。
我从某个博客(可能是stackoveflow)复制了此函数,它将一个字数组转换为字节数组,以便在pako.js中使用。
它用于为zlib压缩字符串充气。
当字符串较小时,它不会超出调用堆栈,但是对于较长的字符串,它将超过它。
我尝试用setTimeout重写它,但是它变得非常慢。 你们有什么建议吗?
谢谢。
const wordToByteArray = function (word, length) {
let ba = [];
let i;
let xFF = 0xFF;
if (length > 0)
ba.push(word >>> 24);
if (length > 1)
ba.push((word >>> 16) & xFF);
if (length > 2)
ba.push((word >>> 8) & xFF);
if (length > 3)
ba.push(word & xFF);
return ba;
};
const wordArrayToByteArray = function(wordArray, length) {
if (wordArray.hasOwnProperty("sigBytes") && wordArray.hasOwnProperty("words")) {
length = wordArray.sigBytes;
wordArray = wordArray.words;
}
let result = [];
let bytes;
let i = 0;
while (length > 0) {
bytes = wordToByteArray(wordArray[i], Math.min(4, length));
length -= bytes.length;
result.push(bytes);
i++;
}
return [].concat.apply([], result);
};
解决方案 谢谢您的回答,这就是解决方案。
...
while (length > 0) {
bytes = wordToByteArray(wordArray[i], Math.min(4, length));
length -= bytes.length;
bytes.forEach(function (byte) {
result.push(byte);
});
i++;
}
return result;
};
答案 0 :(得分:3)
[].concat.apply([], result);
可能是您的问题;这实际上是在说“请致电[].concat(result[0], result[1], result[2], ..., result[result.length - 1])
。对于较大的输入,您可能会按比例分配较大的result
。Per MDN's warnings on apply
:
但是要注意:以这种方式使用
apply
时,您将冒超出JavaScript引擎的参数长度限制的风险。应用带有过多参数(想想成千上万个参数)的函数的结果因引擎而异(JavaScriptCore已硬编码argument limit of65536
),因为该限制(甚至包括任何过大的参数的性质,堆栈行为)未指定。一些引擎将引发异常。更有害的是,其他人将任意地限制实际传递给应用函数的参数数量。为了说明这后一种情况:如果这样的引擎有四个参数的限制(实际的限制当然要高得多),则示例中的参数5, 6, 2, 3
会传递给apply
而不是整个数组。
如果您的result
数组确实很大,尝试将成千上万(或更多)个参数传递给Array.concat
可能会炸毁您的堆栈。 MDN文档建议,在像您这样的场景中,您可以使用混合策略来避免栈被炸毁,无论大小如何,一次apply
一次处理一大堆参数,而不是所有参数。
幸运的是,someone has already provided a guide on how to do this safely;只需使用它,并与extend
中的每个子数组显式循环到result
。
答案 1 :(得分:0)
您的result
数组非常大。这里的问题出在apply
方法中,其中您提供了result
作为参数。函数的参数被压入堆栈,这会导致堆栈溢出。