ScriptSharp: Taking care of 'this'

Making sure ‘this’ points to exactly what you think it does in Javascript is one of the challenges that a new programmer to the language has to overcome. Script# makes this somewhat easy for us because it tries to make sure it points to exactly what we’d expect it to if we were writing a normal C# app.

Take this snippet, for example:

jQueryObject buttons = jQuery.Select(".homepageCreateButton");

buttons.MouseOver(delegate(jQueryEvent e) {  
 jQueryObject button = jQuery.This;
});

Here I’m selecting some buttons and applying a click handler. The generated code here is as you would expect, where jQuery. This clearly translates to $(this):

var buttons = $('.homepageCreateButton');  
buttons.mouseover(function(e) {  
   var button = $(this); 
});

What happens though when I start using the C# keyword ‘this’ in my delegate?

jQueryObject buttons = jQuery.Select(".homepageCreateButton"); 

buttons.MouseOver(delegate(jQueryEvent e) {  
  jQueryObject button = jQuery.This; object a = this; });

This gets compiled to:

var buttons = $('.homepageCreateButton'); 

buttons.mouseover(ss.Delegate.create(this,  
   function(e) { var button = $(this); var a = this; }));

.. which is not quite the same thing. As soon as the Script# compiler has detected that I am making use of the ‘this’ pointer it wraps the delegate call in a method and changes the context of the code inside the delegate so that ‘this’ points to the current instance of the class. This is of course the exact behaviour we would expect and love in C#, and for the most part this is also a good thing in Javascript. By the way, this transformation also happens if you implicitly access a class-level member without using the ‘this’ keyword.

However, look at what it has done to our jQuery selector; we expected ‘this’ to be the current element that we are handling the ‘mouseover’ event for, but now that has changed and we are effectively selecting the current instance of the class through a jQuery selector, which of course is nonsense.

To get around this and make sure that you’re accessing the actual object that you want inside the delegate, you should make use of the CurrentTarget property on jQueryEvent:

jQueryObject button = jQuery.FromElement(e.CurrentTarget)  

Just be careful when you intend to use ‘this’ and ‘jQuery.This’ together in a delegate, as they will not behave as you would expect in this case.