2013-05-01 33 views
1

下面是我刚开始工作的一些代码(化身发生器实验)。我希望能够点击按钮并更改画布元素的位置,但我遇到了一些麻烦。访问全局变量和异步问题

在按钮上我CONSOLE.LOG出canvasTop click事件函数...

console.log(this.canvasTop); 

...然而,它就会不确定。除了这个点击事件函数外,我可以在代码中的任何地方访问变量。这是为什么?

另一件事是接下来的两行...

this.canvasTop += 10; 
AvatarGenerator.canvas(); 

...第一个在这些线路上我想迭代canvasTop值,并在第二行调用函数绘制帆布。但是,似乎第二行在第一行之前运行(是的,我知道JS是异步的),这意味着直到下次单击按钮时,canvas元素才会移动。我该如何解决这个问题?

在此先感谢!

代码:

AvatarGenerator = { 

    canvasTop: 50, 
    canvasLeft: 50, 
    canvas: $('#canvas')[0], 
    context: canvas.getContext('2d'), 

    init: function() { 
     AvatarGenerator.canvas(); 
     AvatarGenerator.toolBox(); 
    }, 

    canvas: function() { 
     console.log(this.canvasTop); // <-- 50 
     this.context.beginPath(); 
     this.context.moveTo(this.canvasLeft, this.canvasTop); 
     this.context.lineTo(300, 300); 
     this.context.stroke(); 
    }, 

    toolBox: function() { 
     var moveLeftBtn = $('#moveLeftBtn'); 

     moveLeftBtn.on('click', function(){ 
      console.log(this.canvasTop); // <-- undefined, why? 

      this.canvasTop += 10; 
      AvatarGenerator.canvas(); 
     }); 
    } 
}; 
+3

'this'是不是你认为是。 'console.log(this)'解决方案应该比较明显。 – 2013-05-01 15:24:21

回答

4

的点击处理程序被调用在不同的环境,所以this不指向你的对象了。

试试这个:

var self = this; 
moveLeftBtn.on('click', function(){ 
    console.log(self.canvasTop); 

    self.canvasTop += 10; 
    AvatarGenerator.canvas(); 
}); 

或者,现代浏览器,您可以将对象绑定到你的函数,所以你不需要self

moveLeftBtn.on('click', function(){ 
    console.log(this.canvasTop); 

    this.canvasTop += 10; 
    AvatarGenerator.canvas(); 
}.bind(this)); 
//^^^^^^^^^^ this determines what 'this' in the callback function is pointing to 
+2

在这种情况下,你也可以使用'AvatarGenerator'而不是'this'或'self',但是。 – 2013-05-01 15:27:37

+0

+1我建议看看一个jQuery插件模板,看看'base'的传统用法,但'self'在这个例子中是一样的东西,并会工作:) – Archer 2013-05-01 15:28:13

+0

@KevinB你绝对正确:) – robertklep 2013-05-01 15:28:14