膨大な配列を持つCodePenでの奇妙なJavaScriptの動作

ShrekOverflow:

次のコードは、サイレント論理エラーを実行します。

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

考えられる動作:

  • avg2番目のforループの後の変数は2倍にし、配列の長さは1億1,400万にする必要があります。

  • メモリエラーが発生します。

スクリプトとして実行したときの出力:

  • avg 2番目のforループの後も変化しません。
  • アレイの長さが114ミルではない(Chrome 2-3M、Firefox Dev 5ミル、MS Edge 788k)。
Benjamin Gruenbaum:

あなたがCodepenでコードを書くとき-彼らは実際にそれをそのまま実行するのではなく、最初にそれにいくつかの変換を適用します。

彼らはそれを抽象構文ツリー解析し、ループを見つけて、時間が経過しすぎるとループの実行を停止するように明示的命令挿入します。

あなたがするとき:

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内のフレームコードを調べることで確認できます。

shouldStopLoopコード内に呼び出しを挿入します。彼らstopExecutionOnTimeoutは次のようなスクリプトを持っています(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 [email protected].";
};

自分で実行したい場合-JSBinには同様の機能があり、ループ保護ライブラリとしてオープンソース化されています-500 LoC未満。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

javascriptで配列を作成するときの奇妙な動作

分類Dev

Matlab配列での奇妙な動作

分類Dev

C配列での奇妙な動作

分類Dev

数値文字列を持つString.replaceAll()の奇妙な動作

分類Dev

cdkCdkDragDropを使用した2つの配列の奇妙な動作

分類Dev

Javascript / ReactNativeでの奇妙な配列の動作

分類Dev

配列で最大数を見つけるときの奇妙な動作

分類Dev

JavaScriptで配列をループしているときの奇妙な動作

分類Dev

Javaの奇妙な配列の動作

分類Dev

C ++の奇妙な配列の動作

分類Dev

Javascriptで文字列を分割する際の奇妙な動作

分類Dev

大きな配列でのC ++ / CUDAの奇妙な動作

分類Dev

特定の値を持つreallocの奇妙な動作

分類Dev

PHP連想配列の奇妙な動作

分類Dev

Cで文字列配列の要素を出力するときの奇妙な動作

分類Dev

配列のリストでのContains()の奇妙な動作

分類Dev

OneToMany関係を持つHibernateからの奇妙な動作

分類Dev

asp.netとjavascript配列の奇妙な動作

分類Dev

Cでの奇妙な行列配列の動作

分類Dev

状態更新後の配列マップでの奇妙な動作

分類Dev

配列NodeJS / CronでのforEachの奇妙な動作

分類Dev

データの配列で$ ampを使用するPHPstr_replaceの奇妙な動作

分類Dev

配列の終わりを過ぎたNumpyの奇妙な動作

分類Dev

zshの「options」配列を使用したdeclare / typesetの奇妙な動作

分類Dev

PhantomJS / WebKitでの奇妙なJavaScriptの動作

分類Dev

JavaScriptでの奇妙な関数の動作

分類Dev

Json ObjectManipulationでのJavascriptの奇妙な動作

分類Dev

AJAXPostでの奇妙なJavascript / PHPの動作

分類Dev

Firefox での javascript RegExp の奇妙な動作

Related 関連記事

  1. 1

    javascriptで配列を作成するときの奇妙な動作

  2. 2

    Matlab配列での奇妙な動作

  3. 3

    C配列での奇妙な動作

  4. 4

    数値文字列を持つString.replaceAll()の奇妙な動作

  5. 5

    cdkCdkDragDropを使用した2つの配列の奇妙な動作

  6. 6

    Javascript / ReactNativeでの奇妙な配列の動作

  7. 7

    配列で最大数を見つけるときの奇妙な動作

  8. 8

    JavaScriptで配列をループしているときの奇妙な動作

  9. 9

    Javaの奇妙な配列の動作

  10. 10

    C ++の奇妙な配列の動作

  11. 11

    Javascriptで文字列を分割する際の奇妙な動作

  12. 12

    大きな配列でのC ++ / CUDAの奇妙な動作

  13. 13

    特定の値を持つreallocの奇妙な動作

  14. 14

    PHP連想配列の奇妙な動作

  15. 15

    Cで文字列配列の要素を出力するときの奇妙な動作

  16. 16

    配列のリストでのContains()の奇妙な動作

  17. 17

    OneToMany関係を持つHibernateからの奇妙な動作

  18. 18

    asp.netとjavascript配列の奇妙な動作

  19. 19

    Cでの奇妙な行列配列の動作

  20. 20

    状態更新後の配列マップでの奇妙な動作

  21. 21

    配列NodeJS / CronでのforEachの奇妙な動作

  22. 22

    データの配列で$ ampを使用するPHPstr_replaceの奇妙な動作

  23. 23

    配列の終わりを過ぎたNumpyの奇妙な動作

  24. 24

    zshの「options」配列を使用したdeclare / typesetの奇妙な動作

  25. 25

    PhantomJS / WebKitでの奇妙なJavaScriptの動作

  26. 26

    JavaScriptでの奇妙な関数の動作

  27. 27

    Json ObjectManipulationでのJavascriptの奇妙な動作

  28. 28

    AJAXPostでの奇妙なJavascript / PHPの動作

  29. 29

    Firefox での javascript RegExp の奇妙な動作

ホットタグ

アーカイブ