Javascript 如何重写此代码以避免使用全局变量?

Javascript 如何重写此代码以避免使用全局变量?,javascript,Javascript,这个问题在过去再次出现在我身上,我使用了全局变量,但我想知道还有什么其他方法来处理它 代码是我正在玩的 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,3

这个问题在过去再次出现在我身上,我使用了全局变量,但我想知道还有什么其他方法来处理它

代码是我正在玩的

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();

如何避免使用全局变量?

将其作为参数传递,并返回修改后的变量:

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提出的更像类的方法。

您可以使用对象,如图所示


重要完全披露,此代码未按原样运行。虽然我坚持我的一般方法,但setInterval仍然需要传递正确的上下文。我已经修正了我的答案,以反映上述情况,并在fiddle链接中添加了一个工作示例。如果上下文传递让您感到困惑,请使用其他方法。

您可以使用模块模式-这是一种提供封装的简洁方式:

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

阅读更多关于它的信息。

这很吸引人,而且确实很容易将所有东西都包装在一个对象或一个生活中,这个对象或生活可以照顾全球人,但这并不会给聚会带来任何新的东西。我建议使用一个简单的闭包,所有变量都设置在
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);
var init=function()
{
变量x,y,dx,dy,ctx=document.getElementById('canvas')。getContext('2d');
返回setInterval(函数()
{
ctx.clearRect(0,0300);
ctx.beginPath();
弧(x,y,10,0,数学π*2,真);
ctx.closePath();
ctx.fill();
x+=dx;
y+=dy;
},10);
};

var iv=init()//将其全部封装在一个自动执行的函数声明中<代码>(函数(){/*您的代码*/})(
在函数中声明它们?如果这些变量在多个函数中使用,我不明白为什么不应该将它们添加到
窗口
对象中。@DCoder如chumkiu的答案所示?是的,这是我最初的建议,但和答案可能更合适。@DCoder抱歉。你的建议早在我回答之前(我用英语写得很慢)。我删除它也是因为加布里埃尔的答案更完整:-)谢谢,我真的不知道为什么我一开始就拉小提琴。
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);