[英]Largest array I can safely pass to function.apply() / spread operator
The "JavaScriptonic" way to calculate the maximum value of an array is: 计算数组最大值的“JavaScriptonic”方法是:
Math.max.apply(null, array)
However, this errors with "maximum call stack size exceeded" on arrays of size 2^16 (Chrome, Safari) or 2^18 (Firefox). 但是,在大小为2 ^ 16(Chrome,Safari)或2 ^ 18(Firefox)的阵列上出现“超出最大调用堆栈大小”的错误。 See https://jsfiddle.net/dxcot206/
见https://jsfiddle.net/dxcot206/
How can I use this technique safely? 我怎样才能安全地使用这种技术? Is there a largest array length for which this technique is guaranteed to work?
是否有最大的阵列长度可以保证这种技术有效?
Might the answer be different in a WebWorker, since background threads often have smaller stack sizes? 在WebWorker中,答案可能会有所不同,因为后台线程通常具有较小的堆栈大小?
How can I use this technique safely?
我怎样才能安全地使用这种技术?
Not at all. 一点也不。
Is there a largest array length for which this technique is guaranteed to work?
是否有最大的阵列长度可以保证这种技术有效?
No, there are no requirements for such things in the spec, all you are seeing are implementation-dependent " we don't support unreasonably large argument lists above N
" restrictions. 不,规范中没有对此类内容的要求,您所看到的都是依赖于实现的“ 我们不支持超过
N
无理大型参数列表 ”限制。
The "JavaScriptonic" way to calculate the maximum value of an array is:
Math.max.apply(null, array)
计算数组最大值的“JavaScriptonic”方法是:
Math.max.apply(null, array)
It's just short, but not very efficient, and as you have seen might not work. 它只是短暂的,但效率不高,而且你所看到的可能不起作用。 Better use
array.reduce((a, b) => Math.max(a, b))
. 最好使用
array.reduce((a, b) => Math.max(a, b))
。
Is there a largest array length for which this technique is guaranteed to work?
是否有最大的阵列长度可以保证这种技术有效? Might the answer be different in a WebWorker, since background threads often have smaller stack sizes?
在WebWorker中,答案可能会有所不同,因为后台线程通常具有较小的堆栈大小?
To help answer your second (2) questions in a particular environment, here's a script you can run that uses a binary search to figure out the answer: 为了帮助回答特定环境中的第二(2)个问题,这里是一个可以运行的脚本,它使用二进制搜索来找出答案:
(function () {
// Returns whether or not the action threw an exception.
function throwsException(action) {
try {
action();
} catch (e) {
return true;
}
return false;
}
// Performs the action for various values between lower and upper and returns
// the maximum value for the action to return true.
function findMaxValueForAction(action, lower, upper) {
var best;
while (upper - lower > 1) {
var previousUpper = upper;
var guess = Math.floor((lower + upper) / 2);
if (action(guess)) {
// If the action is successful then the lower needs to be updated to what just succeeded.
lower = guess;
// Is the (successful) lower better than the current best?
if (best === undefined || lower > best) {
// If so update the current best.
best = lower;
}
} else {
// If the action was unsuccessful the new upper bound is 1 less than what we just tried.
upper = guess - 1;
}
}
return best;
}
var maxArraySize = findMaxValueForAction(function (value) {
return !throwsException(function () {
var array = new Array(value);
});
}, 0, Number.MAX_SAFE_INTEGER);
var maxArrayApplySize = findMaxValueForAction(function (value) {
return !throwsException(function () {
var array = new Array(value);
Math.max.apply(null, array);
});
}, 0, maxArraySize);
return [
'Max "value" for "new Array(value)": ' + maxArraySize,
'Max "value" for "Math.max.apply(null, new Array(value))": ' + maxArrayApplySize
];
})().forEach(function(message) { console.log(message) });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.