Search code examples
javascriptprototype

Try to access member variable in prototype method


I'm first to OOP style in js, and this scope is very confusing to me.

$(document).ready(function() {
  $("#cv").attr({
    width: '860px',
    height: '645px'
  });
  var ctx = new Blackboard($("#cv"));
});

function Blackboard(canvas) {
  this.canvas = canvas;
  this.ctx = this.canvas.get(0).getContext("2d");
  this.drawing = false;
  this.canvas.on('mousedown', this.press);
  this.canvas.on('mousemove', this.move);
  this.canvas.on('mouseup', this.end);
  this.setShape();
}

Blackboard.prototype.setShape = function(color, width) {
  this.color = 'white';
  this.width = 1;
  if (color != null) {
    this.color = color;
  }
  if (width != null) {
    this.width = width;
  }
  this.ctx.strokeStyle = this.color;
  this.ctx.lineWidth = this.width;
}

Blackboard.prototype.press = function(event) {
  console.log(this.ctx); // undefined!
  this.ctx.beginPath();
  this.ctx.moveTo(event.pageX, event.pageY);
  this.drawing = true;
}

Blackboard.prototype.move = function(event) {
  if (this.drawing) {
    this.ctx.lineTo(event.pageX, event.pageY);
    this.ctx.stroke();
  }
}

Blackboard.prototype.end = function(event) {
  this.drawing = false;
}

$("#cv") is canvas element.

As I mentioned in comment, every this.ctx in prototype methods are undefined. Though I searched explanations about prototype more detail, I can't find what I'm misunderstanding about scope of this.


Solution

  • You are in an event handler which this does not refer to a Blackboard. Use .bind in your calls to on.

    this.end = this.end.bind(this);
    this.canvas.on('mouseup', this.end);