类方法不是函数?

时间:2017-02-18 02:17:52

标签: javascript function class methods typeerror

我得到"未捕获的TypeError:this.time_to_x不是函数"将一些开源ES5代码合并到我的ES6 Class中时。这是课程(我已经删除了一些批量,但大多数必要的东西都在那里)。假设调用Diamond()。这一行得到错误:x = this.time_to_x(frame.time);

为什么time_to_x()不被视为函数?

export default class TimelinePanel {

  constructor(ctx) {
    this.ctx = ctx;
    this.ctx_wrap = ctx; 
  }

  create (ctx) {
    this.rect({ctx, x: 20, y: 15, width: 130, height: 10}); // ***
    this.drawLayerContents();
  }

  Diamond(frame, y) {

    var x, y2;

    x = this.time_to_x(frame.time);
    y2 = y + LINE_HEIGHT * 0.5  - DIAMOND_SIZE / 2;

    var self = this;
    var isOver = false;

    this.path = function() {
        this.ctx_wrap
            .beginPath()
            .moveTo(x, y2)
            .lineTo(x + DIAMOND_SIZE / 2, y2 + DIAMOND_SIZE / 2)
            .lineTo(x, y2 + DIAMOND_SIZE)
            .lineTo(x - DIAMOND_SIZE / 2, y2 + DIAMOND_SIZE / 2)
            .closePath();
    };
  }

  drawLayerContents() {
    // ...
    for (i = 0; i < il; i++) {
        // ...
        for (j = 0; j < values.length; j++) {
            // Dimonds
            frame = values[j];
            renderItems.push(new this.Diamond(frame, y));
        }
    }
  }

  y_to_track(y) {
    if (y - MARKER_TRACK_HEIGHT < 0) return -1;
    return (y - MARKER_TRACK_HEIGHT + scrollTop) / LINE_HEIGHT | 0;
  }

  x_to_time(x) {
    var units = time_scale / tickMark3;
    return frame_start + ((x - LEFT_GUTTER) / units | 0) / tickMark3;
  }

  time_to_x(s) {
    var ds = s - frame_start;
    ds *= time_scale;
    ds += LEFT_GUTTER;
    return ds;
  }
}

2 个答案:

答案 0 :(得分:2)

因为你拥有它的方式它假设time_to_x来自闭合,而不是来自this。在this中没有这样的函数,因此this.time_to_x名称返回undefined,这实际上不是函数。

我建议像这样: 将var self = this;放在类中但在Diamond方法之外。 然后在self.time_to_x()内拨打Diamond

答案 1 :(得分:2)

当您执行this.Diamond时,您正在创建new this.Diamond(frame, y)类的实例。因此,在函数内部,this是这个新实例,而不是最初创建它的TimelinePanel实例。因此,this没有TimelinePanel的成员。

因为似乎y_to_trackx_to_time没有使用this,您可以将它们设为静态(在它们之前添加关键字static)并将其称为以下:TimelinePanel.y_to_track

如果您需要访问绑定到TimelinePanel的特定实例的方法,那么除了将此实例传递给Diamond构造函数或重构TimelinePanel之外,我没有看到任何其他解决方案。在Diamond构造函数周围使用闭包。

在任何情况下,您似乎都在尝试复制类似Java的内部类的行为(例如,您可以使用ClassName.this访问容器类实例或只访问容器类成员),没有这样的JS中的东西(至少有class)。

编辑:我刚刚注意到您正在访问TimelinePanel的{​​{1}}成员,而您无法将其作为班级成员。最简单的似乎是将ctx_wrap传递给TimelinePanel构造函数:DiamondDiamond(frame, y, panel)。如果将new this.Diamond(frame, y, this)添加为Diamond的成员,则会产生疑问。