Coffeescript:为什么这个类中的函数说它的参数是未定义的?

时间:2013-06-05 04:39:44

标签: javascript coffeescript

当我运行我的代码时,它给了我这个错误:

  

TypeError:pivot未定义

这是错误所指的相关类:

class Hero
  constructor: (@color, @direction, @x, @y) ->
  pivots: []
  addPivot: (pivot) -> @pivots.push(pivot)
  onPivot: (pivot) -> pivot.x == @x && pivot.y == @y
  applyPivots: () ->
    indexToRemove = -1
    for i in [0..@pivots.length - 1]
      pivot = @pivots[i]
      if (@onPivot(pivot))
        @direction = pivot.direction
        indexToRemove = i
    @pivots.splice(indexToRemove, 1)

为什么会这样?这是它正在生成的javascript:

  Hero = (function() {
    function Hero(color, direction, x, y) {
      this.color = color;
      this.direction = direction;
      this.x = x;
      this.y = y;
    }

    Hero.prototype.pivots = [];

    Hero.prototype.addPivot = function(pivot) {
      return this.pivots.push(pivot);
    };

    Hero.prototype.onPivot = function(pivot) {
      return pivot.x === this.x && pivot.y === this.y;
    };

    Hero.prototype.applyPivots = function() {
      var i, indexToRemove, pivot, _i, _ref;

      indexToRemove = -1;
      for (i = _i = 0, _ref = this.pivots.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
        pivot = this.pivots[i];
        if (this.onPivot(pivot)) {
          this.direction = pivot.direction;
          indexToRemove = i;
        }
      }
      return this.pivots.splice(indexToRemove, 1);
    };

    return Hero;

  })();

该错误出现在:

  return pivot.x === this.x && pivot.y === this.y;

1 个答案:

答案 0 :(得分:4)

您的for循环限制存在问题。假设您的@pivots数组为空,那么for中的applyPivots循环将如下所示:

for i in [0..-1]
  #...

因此它将从零开始并下降到-1。但@pivots为空,所以:

pivot = @pivots[i]

会在undefined中给你一个pivot,一切都会在一连串的混乱中崩溃。

您可能希望使用for element in array循环的for形式:

applyPivots: () ->
  indexToRemove = -1
  for pivot, i in @pivots
    if(@onPivot(pivot))
      @direction = pivot.direction
      indexToRemove = i
  @pivots.splice(indexToRemove, 1) if(indexToRemove >= 0)
如果没有找到任何东西(即indexToRemove == -1),大概你不想做任何事情,所以我把它扔进了免费的。

我认为你也可以走得更远。像这样:

for pivot, i in @pivots when @onPivot(pivot)
  @direction = pivot.direction
  @pivots.splice(i, 1)
  break

您可以使用when跳过您不关心的循环中的内容,因为您只想从@pivots删除一件事,您可以尽快摆脱循环正如你所发现的那样。这假设@pivots只会匹配,如果有多次点击并且您真的想要最后一次点击,那么您可以通过添加by -1来向后搜索:

for pivot, i in @pivots by -1 when @onPivot(pivot)
  # same as above...

您可以在the fine manual中找到有关bywhen和其他循环好吃的详细信息。


虽然我在这里,但不要这样做:

class Hero
  pivots: []

这会将您的数组附加到Hero的原型,以便Hero的所有实例共享它。所以,如果你这样做:

h1 = new Hero
h2 = new Hero
h1.pivots.push('pancakes')

然后您还会在'pancakes'中看到h2.pivots。您应该在构造函数中为每个实例提供自己的数组:

class Hero
  constructor: (@color, @direction, @x, @y) ->
    @pivots = [ ]

同样的谨慎适用于您可能想要放入课堂的任何可变值。数字和字符串等不可变值很好,你只能为这些值赋值,而新值会影响原型的值,所以不会造成任何伤害。