CodePen中奇怪的JavaScript行为与庞大的数组 [英] Strange JavaScript behavior in CodePen with humongous arrays

查看:100
本文介绍了CodePen中奇怪的JavaScript行为与庞大的数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码执行无提示逻辑错误:

The following code performs a silent logical error:

const arr = [];
class Point{
  constructor(){
    this.x = Math.random() * 1000000;
    this.y = Math.random() * 1000000;
  }
}
console.time('foo');
let avg = 0;

for(let i = 0; i < 114000000; i++ ){
  arr.push(new Point());
  avg += arr[i].x / 1000;
}
console.log(avg, arr.length);

// shouldn't this double the avg ?
for(let i = 0; i < 114000000; i++ ){
  avg += arr[i].x / 1000;
}

console.log(avg, arr.length);
console.timeEnd('foo');

CodePen - http://codepen.io/darkyen/pen/yOPMZg?editors=0010

CodePen - http://codepen.io/darkyen/pen/yOPMZg?editors=0010

可能的行为:


  • 第二个for循环后变量 avg 应加倍并且长度为数组应该是1.14亿。

  • The variable avg after the second for loop should be doubled and The length of array should be 114 million.

我应该收到内存错误。

作为脚本运行时的输出:

Output when run as a script:


  • avg 在第二个for循环后不会改变。

  • 阵列的长度不是114 Mil,(Chrome 2-3M,Firefox Dev 5 Mil,MS Edge 788k)。

  • avg Does not change after the second for loop.
  • Length of the array is not 114 Mil, (Chrome 2-3M, Firefox Dev 5 Mil, MS Edge 788k).

推荐答案

当您在Codepen中编写代码时 - 它们实际上并不按原样执行,而是首先应用对它进行了一些转换。

When you write code in Codepen - they actually don't execute it as-is but rather first apply some transformations to it.

他们将其解析为抽象语法树

They parse it into an abstract syntax tree, find loops and insert instructions explicitly to stop executing the loop if too much time has passed.

你这样做:

for(let i = 0; i < 114000000; i++ ){
  arr.push(new Point());
  avg += arr[i].x / 1000;
}

您的代码运行如下:

for (var i = 0; i < 114000000; i++) {
    if (window.CP.shouldStopExecution(1)) { // <- injected by Codepen!!!
        break;
    }
    arr.push(new Point());
    avg += arr[i].x / 1000;
    iter++;
}

您可以通过检查CodePen内部的框架代码来看到这一点。

You can see this by inspecting the frame code inside CodePen itself.

他们在您的代码中注入 shouldStopLoop 调用。
他们有一个名为 stopExecutionOnTimeout 的脚本,它做类似这样的事情(源自Codepen):

They inject shouldStopLoop calls inside your code. They have a script called stopExecutionOnTimeout which does something like this (source from Codepen):

 var PenTimer {
   programNoLongerBeingMonitored:false,
   timeOfFirstCallToShouldStopLoop:0, // measure time
   _loopExits:{}, // keep track of leaving loops
   _loopTimers:{}, // time loops
   START_MONITORING_AFTER:2e3, // give the script some time to bootstrap
   STOP_ALL_MONITORING_TIMEOUT:5e3, // don't monitor after some time
   MAX_TIME_IN_LOOP_WO_EXIT:2200, // kill loops over 2200 ms
   exitedLoop:function(o) { // we exited a loop 
     this._loopExits[o] = false; // mark
   },
   shouldStopLoop:function(o) { // the important one, called in loops
      if(this.programKilledSoStopMonitoring)  return false; // already done
      if(this.programNoLongerBeingMonitored)return true;
      if(this._loopExits[o])  return false; 
      var t=this._getTime(); // get current time
      if(this.timeOfFirstCallToShouldStopLoop === false) 
        this.timeOfFirstCallToShouldStopLoop = t;
        return false;
      }
      var i= t - this.timeOfFirstCallToShouldStopLoop; // check time passed
      if(i<this.START_MONITORING_AFTER) return false; // still good   
      if(i>this.STOP_ALL_MONITORING_TIMEOUT){
        this.programNoLongerBeingMonitored = true;
        return false;
      }
      try{
        this._checkOnInfiniteLoop(o,t);
      } catch(n) {
        this._sendErrorMessageToEditor(); // send error about loop
        this.programKilledSoStopMonitoring=false;
        return true; // killed
      }
      return false; // no need
   },
   _sendErrorMessageToEditor:function(){/*... */
      throw "We found an infinite loop in your Pen. We've stopped the Pen from running. Please correct it or contact support@codepen.io.";
};

如果你想自己运行它 - JSBin有类似的功能,它们有开源作为循环保护库 - 低于500 LoC。

If you want to run it yourself - JSBin has similar functionality and they have open sourced it as the loop-protect library - under 500 LoC.

这篇关于CodePen中奇怪的JavaScript行为与庞大的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆