开发者

How to use keyword this in a mouse wrapper in right context in Javascript?

I'm trying to write a simple wrapper for mouse behaviour. Th开发者_JAVA百科is is my current code:

function MouseWrapper() {

  this.mouseDown = 0;  
  this.OnMouseDownEvent = null;
  this.OnMouseUpEvent = null;
  document.body.onmousedown = this.OnMouseDown;  
  document.body.onmouseup = this.OnMouseUp;
}

MouseWrapper.prototype.Subscribe = function (eventName, fn) {

  // Subscribe a function to the event
  if (eventName == 'MouseDown') {
    this.OnMouseDownEvent = fn;
  } else if (eventName == 'MouseUp') {
    this.OnMouseUpEvent = fn;
  } else {    
    alert('Subscribe: Unknown event.'); 
  }  
}  


MouseWrapper.prototype.OnMouseDown = function () {  
  this.mouseDown = 1;  
  // Fire event
  $.dump(this.OnMouseDownEvent);
  if (this.OnMouseDownEvent != null) {
    alert('test');
    this.OnMouseDownEvent();
  }
}

MouseWrapper.prototype.OnMouseUp = function () {

  this.mouseDown = 0;
  // Fire event
  if (this.OnMouseUpEvent != null) {
    this.OnMouseUpEvent();
  }  
}

From what I gathered it seems that in MouseWrapper.prototype.OnMouseUp and MouseWrapper.prototype.OnMouseDown the keyword "this" doesn't mean current instance of MouseWrapper but something else. And it makes sense that it doesn't point to my instance but how to solve the problem?

I want to solve the problem properly I don't want to use something dirty.

My thinking: * use a singleton pattern (mouse is only one after all) * pass somehow my instance to OnMouseDown/Up - how?

Thank you for help!


The above solution is fine but a more re-usable way is to "bind" your method to a context by creating a method that creates that closure for you. For example

Function.bind = function(method, context) {
  return function() {
    return method.apply(context, arguments);
  }
}

Following Slaks's example, you would have:

document.body.onmousedown = Function.bind(this.OnMouseDown,this);
document.body.onmouseup = Function.bind(this.OnMouseUp, this); 

or you could do it to Function.prototype for syntactic sugar.

Function.prototype.bind = function(context) {
  return function() {
    // since this is a prototype method, "this" is the method to be called
    return this.apply(context, arguments);
  }
}

document.body.onmousedown = this.OnMouseDown.bind(this);
document.body.onmouseup = this.OnMouseUp.bind(this); 

You could also bind arguments to be called as well as the context... ask if you're interested.

The singleton approach, though it works, is a hack. It's adding globals instead of properly addressing the issues at hand. It means if you needed the behavior in two places, it wouldn't work.


In Javascript, unlike most languages, the value of the this keyword is determined when the function is called.

For example:

var dumper = function() { alert(this); };
var str1 = "A";
str1.dump = dumper;
str1.dump();        //Alerts A

var str2 = "B";
str2.dump = str1.dump;
str2.dump();        //Alerts B

When the browser calls your event handler, it calls it in the context of the DOM element, so this isn't what you think it is.

To work around this, you need to use an anonymous method that calls your handlers in the right context.

For example:

var self = this;

document.body.onmousedown = function(e) { return self.OnMouseDown(e); };
document.body.onmouseup = function(e) { return self.OnMouseUp(e); };

Also, you should not handle events like this.

Instead, call attachEvent / addEventListener.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜