2

この問題は過去に再び発生し、グローバル変数を使用しましたが、他の方法で対処する方法を知りたいです。

コードは、私が現在遊んでいるhtml5 キャンバス チュートリアルからのものです。

var x = 150;
var y = 150;
var dx = 2;
var dy = 4;
var ctx;

function init() {
  ctx = $('#canvas')[0].getContext("2d");
  return setInterval(draw, 10);
}

function draw() {
  ctx.clearRect(0,0,300,300);
  ctx.beginPath();
  ctx.arc(x, y, 10, 0, Math.PI*2, true); 
  ctx.closePath();
  ctx.fill();
  x += dx;
  y += dy;
}

init();

グローバル変数の使用を避けるにはどうすればよいですか?

4

4 に答える 4

4

モジュール パターンを使用できます。これは、カプセル化を提供する適切な方法です。

var app = app || {};
app = (function () {
  var x = 150; // all these variables are private
  var y = 150;
  var dx = 2;
  var dy = 4;
  var ctx;

  var draw = function() { // this method is private
    ctx.clearRect(0,0,300,300);
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI*2, true); 
    ctx.closePath();
    ctx.fill();
    x += dx;
    y += dy;
  };

  return {
    init: function() { // this method is public
      ctx = $('#canvas')[0].getContext("2d");
      return setInterval(draw, 10);
    }
  }
}());

app.init(); // init() is public, but all the other vars and functions are not

詳しくはhttp://addyosmani.com/largescalejavascript/#modpatternをご覧ください。

于 2012-10-13T19:37:06.307 に答える
3

ここに示すように、オブジェクトを使用できます

myObj = {
    x: 150,
    y: 150,
    dx: 2,
    dy: 4,
    ctx: null,
    init: function() {
        this.ctx = $('#canvas')[0].getContext("2d");
        return setInterval((function(a){return function(){a.draw()}})(this), 10);
    },
    draw: function() {
        this.ctx.clearRect(0,0,300,300);
        this.ctx.beginPath();
        this.ctx.arc(this.x, this.y, 10, 0, Math.PI * 2, true);
        this.ctx.closePath();
        this.ctx.fill();
        this.x += this.dx;
        this.y += this.dy;
    }
}

myObj.init();

重要完全な開示、このコードはそのままでは機能しません。私は一般的なアプローチを支持していますが、setIntervalに正しいコンテキストを渡す必要があります。上記を反映するように回答を修正し、フィドルリンクに実用的な例を追加しました。コンテキストの受け渡しがわかりにくい場合は、他のアプローチを使用してください。

于 2012-10-13T19:35:49.560 に答える
1

それらをパラメーターとして渡し、変更して返します。

function init() {
  var x = 150;
  var y = 150;
  var dx = 2;
  var dy = 4;
  var ctx = $('#canvas')[0].getContext("2d");
  return setInterval(function() {
    var temp = draw(x, y, dx, dy, ctx);
    x = temp.x;
    y = temp.y;
  }, 10);
}

function draw(x, y, dx, dy, ctx) {
  ctx.clearRect(0,0,300,300);
  ctx.beginPath();
  ctx.arc(x, y, 10, 0, Math.PI*2, true); 
  ctx.closePath();
  ctx.fill();
  x += dx;
  y += dy;
  ret = {};
  ret.x = x;
  ret.y = y;
  return ret;
}

(何を渡す必要があるかは完全にはわかりません。できる場合は、結合を減らすために渡す回数を減らしてください。)

ただし、このソリューションは、@Asadによって提案されたものなどのよりクラスに似た方法よりも劣っています。

于 2012-10-13T19:35:28.573 に答える
1

グローバルを処理するオブジェクトまたは IIFE ですべてをラップするのは魅力的であり、実際には簡単ですが、それはパーティーに新しいものを何ももたらしません。すべての変数がinit関数内に設定されている単純なクロージャーをお勧めします。この関数では、関数を定義して、draw関数がクロージャー変数にアクセスできるようにします。この関数は間隔を設定するためだけに使用されるため、このクロージャーには名前付き関数を含める必要がないため、名前を省略しました。

var init = function()
{
    var x, y, dx, dy, ctx = document.getElementById('canvas').getContext('2d');
    return setInterval(function()
    {
        ctx.clearRect(0,0,300,300);
        ctx.beginPath();
        ctx.arc(x, y, 10, 0, Math.PI*2, true); 
        ctx.closePath();
        ctx.fill();
        x += dx;
        y += dy;
    },10);
};
var iv = init();//<-- best off storing the interval somewhere
//... stop drawing:
clearInterval(iv);

それもそれだけです。

于 2012-10-13T19:49:01.047 に答える