【问题标题】:Coffeescript: function can't call function on the same objectCoffeescript:函数不能在同一个对象上调用函数
【发布时间】:2013-03-02 18:19:50
【问题描述】:

我尝试编写一个简单的coffeescript 脚本。当用户单击鼠标时,它使用easeljs 生成一个小的灰色圆圈。这是代码

$(window).load ->
    game.init()


game=
    init: ->
        canvas= document.getElementById("Canvas")
        alert(canvas)
        @stage= new createjs.Stage(canvas)
        alert(@stage)

        @testshape= new createjs.Shape()
        @testshape.graphics.beginFill("#555")
        @testshape.graphics.rect(50,50,500,500)

        @stage.addChild(@testshape)
        @stage.update()

        window.onmousedown= (ev)->
            alert "click"
            mx=ev.screenX
            my=ev.screenY
            @spawn({x:mx,y:my})

    spawn: (data)->
        alert("spawn")
        x=data.x
        y=data.y

        shape = new createjs.Shape()
        shape.graphics.beginFill("#555")
        shape.graphics.circle(x,y,5)
        @stage.addChild(shape)
        @stage.update()

前两个警报调用工作正常。并且正确创建了 testshape。回调也很好注册:鼠标单击提示警报“单击”。但是方法 spawn 永远不会被调用。我不明白为什么并查看了生成的javascript:

// Generated by CoffeeScript 1.6.1
(function() {
  var game;

  $(window).load(function() {
    return game.init();
  });

  game = {
    gameObjects: [],
    init: function() {
      var canvas;
      canvas = document.getElementById("Canvas");
      alert(canvas);
      this.stage = new createjs.Stage(canvas);
      alert(this.stage);
      this.testshape = new createjs.Shape();
      this.testshape.graphics.beginFill("#555");
      this.testshape.graphics.rect(50, 50, 500, 500);
      this.stage.addChild(this.testshape);
      this.stage.update();
      return window.onmousedown = function(ev) {
        var mx, my;
        alert("click");
        mx = ev.screenX;
        my = ev.screenY;
        return this.spawn({
          x: mx,
          y: my
        });
      };
    },
    spawn: function(data) {
      var shape, x, y;
      alert("rpcspawn");
      x = data.x;
      y = data.y;
      shape = new createjs.Shape();
      shape.graphics.beginFill("#555");
      shape.graphics.circle(x, y, 5);
      this.stage.addChild(shape);
      return this.stage.update();
    }
  };

}).call(this);

javascript 似乎可以正常工作。为什么没有调用 spawn?

更新: 我已将代码更改为

window.onmousedown=(ev)=>

现在该方法被正确调用了。但在方法内部,其他成员不可用。 spawn里面的这个警报

alert(@stage)

返回“未定义”。我也修改了 spawn。它现在也使用粗箭头语法。但这并没有解决问题。只剩下一种方法: init 。自然地,我尝试将 init 更改为粗箭头语法。但是这三种方法都使用粗箭头,原来的问题又回来了:没有调用 spawn。

  • 如果只有回调和可选的 spawn 使用粗箭头,则 spawn 被正确调用。
  • 如果 init 使用粗箭头,则无法调用 spawn。
  • 在任何情况下都不能从 spawn 内部访问其他成员。

更新: 我将其更改为 OOP 编程。游戏现在是一个类,粗箭头的解决方案有效

【问题讨论】:

    标签: javascript html web coffeescript easeljs


    【解决方案1】:

    将您的代码更改为:

    window.onmousedown= (ev)=>
            alert "click"
            mx=ev.screenX
            my=ev.screenY
            @spawn({x:mx,y:my})
    

    (注意=)。

    问题在于,当在事件处理程序的上下文中调用时,@(在 JavaScript 中也称为 this)是 window,而不是 game

    使用=> 将方法绑定到game

    【讨论】:

    • 次要的 nitpick:this 实际上是 windowonmousedown 处理程序中,而不是事件。
    • @LinusGThiel:正确!我会改变的。
    • 这不能按预期工作。 spawn 被正确调用,但在方法 spawn 内部,其他成员不可用。我会相应地更新我的问题
    • 嗯,它解决了你的第一个问题。但是现在你有一个不同的问题。在spawn 内部,检查this。它是什么?应该是game。是 1) 实际上不是 game,还是 2) game,但未完全初始化?
    • 在将游戏作为一个类实现之后,该解决方案就起作用了。我很乐意接受你的回答。我已经投票了,所以答案只被接受但没有再次投票的事实并不意味着我不欣赏你的努力
    【解决方案2】:

    这里的问题是this,您在window.onmousedown 回调中调用this.spawn(),实际上是window 对象,而不是您的game 对象。

    你应该做类似的事情

    var that = this;
    return window.onmousedown = function(ev) {
        var mx, my;
        alert("click");
        mx = ev.screenX;
        my = ev.screenY;
        return that.spawn({
          x: mx,
          y: my
        });
      };
    

    【讨论】:

    • 这就是你在 JS 中修复它的方式,但 CoffeeScript 有一个更好的解决方案。
    • 我明白了..对不起,我对coffeescript了解不多,只知道javascript,但我想我在编译的javascript中发现了问题,不是吗?
    • 是的,如果我没有可用的 bind 方法,那或多或少就是我在 JS 中使用的方法。
    猜你喜欢
    • 1970-01-01
    • 2014-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多