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?
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:
(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) });