0

スコープの問題を解決するのに苦労しています。実際、私は HMI ブラウザ フロントエンドのプロジェクトに取り組んでいます。自動化システムからの変数を視覚化する必要があります。HMI では、ユーザーが異なるページを切り替えることができる必要があります。一般的なプロセス フローを解決するために、読み込み、描画、およびユーザーとのやり取りを調整するステート マシン関数を作成しました。私の問題は、setTimeout を使用して実行関数 (実際には私のステート マシン) を呼び出し、var-scope で問題が発生することです。

次のコードを見てください。

function frontend() {

  // Public properties:
  this.soundEnable = true;

  // Private Properties:
  var p1 = 0;
  var p2 = [1,2,3];
  var p3 = {a:1, b:2, c:3};
  var runState = 1;
  var runWait = false:

  // Public Methods

  // stops the state machine until m_continue is called
  this.m_wait = function() {
    runWait = true;
  }

  // continues the state machine
  this.m_continue = function() {
    if (runWait) {
      runWait = false;
      setTimeout(run, 100);
    }
  }

  // Private Methods

  function drawFrame(finish_callback) {
    ...<Drawing of HMI-Objects on the canvas>...
    finish_callback();
  }

  function run() {
    switch (runState) {
    case 1:
      this.m_stop();
      drawFrame(this.m_continue());
    case 2:
      for(i=0; i<p3.length; i++) {
        p2.push(externalObjectCreator(p3[i]));
      }
    }
    if (!runWait) {
      runState++;
      setTimeout(run, 100);
    }
  }

  // Constructor
  ...<code to assign public and private properties>...

  // Finally call the state machine to activate the frontend
  runState = 1;
  run();
}

問題は run-Function のスコープです。コンストラクターの最後からの最初の呼び出しの場合、すべて問題ありません。run は、すべてのプライベート プロパティにアクセスして操作できます。しかし、後で m_continue から setTimeout を介して、または単独で呼び出されると、プライベート プロパティにアクセスできません。firebug では、パブリック プロパティと関数のみが表示され、必要なプライベート プロパティは表示されません。

グローバル変数の使用は役に立ちますが、不可能です。マルチ モニター ソリューションでは、HMI の別々のバージョンを表示する必要がある 2 つの別々のキャンバス オブジェクトがあるためです。その場合、1 つのブラウザ ウィンドウで並行して実行されるフロントエンドの 2 つのインスタンスが必要です。

誰もその問題の解決策を知っていますか? 私は自分の知識の終わりにいて、完全に混乱しています。

4

2 に答える 2

1

最も簡単な方法は、スコープを次のように定義することです。多くの有名な JavaScript ライブラリもこの手法を使用しています。

this.m_continue = function() {
 that = this;  
 if (runWait) {
      runWait = false;
      setTimeout(that.run, 100);
    }
  }

それ以外の場合は、スコープバインディングを使用することもできますapply

于 2013-01-02T09:56:53.670 に答える
0

run は を使用するため、各 setTimeout で run 関数をバインドする必要がありますthis

setTimeout(run.bind(this), 100);
于 2013-01-02T10:24:17.083 に答える