在回调中调用函数时,使用作用域的问题

时间:2014-03-06 09:39:45

标签: javascript canvas html5-canvas easeljs createjs

在画布内部单击时,它将生成一个球并移动到单击的位置 当球到达其位置时,我希望它自行移除。但我认为我有一个问题 调用removeBall()函数时的范围。

你可以找到她的工作示例:jsfiddle

 /*
  * Main app logic
  */
  function Main() {
    this.canvas = "canvas";
    this.stage = null;
    this.WIDTH = 0;
    this.HEIGHT = 0;
    this.init();
  }

  Main.prototype.init = function() {
    console.clear();
    this.stage = new createjs.Stage(this.canvas);
    this.resize();
    //start game loop
    createjs.Ticker.setFPS(30);
    createjs.Ticker.addEventListener("tick", this.gameLoop);
    //click event handler
    this.stage.on("stagemousedown", function(evt) {
      main.fireBall(evt);
    });
  };

  Main.prototype.fireBall = function(evt) {
    var bal = new Bal(evt.stageX, evt.stageY);
  };

  Main.prototype.resize = function() {
    //resize the canvas to take max width
    this.WIDTH = window.innerWidth;
    this.HEIGHT = Math.floor(window.innerWidth * 9 / 16);
    this.stage.canvas.width = this.WIDTH;
    this.stage.canvas.height = this.HEIGHT;
  };

  Main.prototype.gameLoop = function() {
    //game loop
    main.stage.update();
  };

  /*
   * Ball logic
  */
  function Bal(toX, toY) {
    this.toX = toX ;
    this.toY = toY;
    this.widthPerc = 8;
    this.init();
  }

  Bal.prototype.width = function() {
    return Math.floor(main.stage.canvas.width / 100 * this.widthPerc);
  };

  Bal.prototype.init = function() {
    //create a new ball
    this.ball = new createjs.Shape();
    this.ball.graphics.beginFill("green").drawCircle(0, 0, this.width());
    this.ball.x = (main.stage.canvas.width / 2) - (this.width() / 2);
    this.ball.y = main.stage.canvas.height - 20;
    main.stage.addChild(this.ball);    
    this.move();
  };

  Bal.prototype.move = function() {
    //create a tween to cliked coordinates
    createjs.Tween.get(this.ball).to({
        x: this.toX ,
        y: this.toY ,
        scaleX:0.4,scaleY:0.4,
        rotation: 180
      },
      750, //speed
      createjs.Ease.none
    ).call(this.removeBall); //   <---- How can i pass the correct scope to the called function?
  };

  Bal.prototype.removeBall = function() {
    //try to remove the ball
    main.stage.removeChild(this.ball);
  };

  var main = new Main(); 

2 个答案:

答案 0 :(得分:1)

使用bind的上述解决方案可行,但有一个更好的解决方案。 Bind并非在所有浏览器中都可用(最值得注意的是Safari 5.1,它是一种现代浏览器)。 http://kangax.github.io/es5-compat-table/#Function.prototype.bind

使用call()时,TweenJS内置了对范围函数的支持。只需将范围作为第3个参数传递。

Ball.prototype.move = function() {
  console.log(this.toX +","+this.toY);
  createjs.Tween.get(this.ball).to({
      x: this.toX ,
      y: this.toY ,
      scaleX:0.4,scaleY:0.4,
      rotation: 180
    },
    750, //speed
    createjs.Ease.none
  ).call(this.removeBall, null, this);
};

您还可以传递一组函数参数作为第二个参数。

Tween.call(this.removeBall, [this.ball], this);

答案 1 :(得分:0)

好的找到了解决方案!使用bind()功能。

Bal.prototype.move = function() {
  console.log(this.toX +","+this.toY);
  createjs.Tween.get(this.ball).to({
      x: this.toX ,
      y: this.toY ,
      scaleX:0.4,scaleY:0.4,
      rotation: 180
    },
    750, //speed
    createjs.Ease.none
  ).call(this.removeBall.bind(this));
};