最大的数组我可以安全地传递给function.apply()/ spread运算符

时间:2016-06-25 22:25:32

标签: javascript arrays

calculate the maximum value of an array的“JavaScriptonic”方式是:

Math.max.apply(null, array)

但是,在大小为2 ^ 16(Chrome,Safari)或2 ^ 18(Firefox)的阵列上出现“超出最大调用堆栈大小”的错误。见https://jsfiddle.net/dxcot206/

如何安全使用此技术?是否有最大的阵列长度可以保证这种技术有效?

在WebWorker中,答案可能会有所不同,因为后台线程的堆栈大小通常较小吗?

2 个答案:

答案 0 :(得分:5)

  

我如何安全地使用这种技术?

完全没有。

  

是否有最大的阵列长度可以保证此技术有效?

不,规范中没有对此类内容的要求,您所看到的都是依赖于实现的“我们不支持N ”限制之上的不合理的大型参数列表。

  

计算数组最大值的“JavaScriptonic”方法是:Math.max.apply(null, array)

这只是短暂的,但效率不高,而且你所看到的可能不起作用。更好地使用array.reduce((a, b) => Math.max(a, b))

答案 1 :(得分:0)

  

是否存在保证此技术的最大阵列长度   上班?由于后台线程,WebWorker中的答案可能会有所不同   通常有较小的堆栈大小?

为了帮助回答特定环境中的第二(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) });