tags:

views:

56

answers:

2

I have this code:

function some_object(...) {
   this.data = {...};

   this.do_something = function(...) {
      var arr = [...];

      arr.sort(function (a, b) {
         return this.data[a] - this.data[b];
      });  
   }
}

However it's not working I think because this cannot be accessed in sort - another this is seen there for some reason, not the this of enclosing outer object.

What to do? thanks

+6  A: 

The different this is because the the anonymous function (its own closure) called by arr.sort calls the function with this being set to a different item than your main object. In an Array.sort, I am not actually sure what this is set to, but it is probably the Array you are sorting. A normal work around in this situation is to use another variable:

function some_object(...) {
   var so = this; // so = current `this`
   this.data = {...};

   this.do_something = function(...) {
      var arr = [...];

      arr.sort(function (a, b) {
         return so.data[a] - so.data[b];
      });  
   }
}
Doug Neiner
thanks, but is this the accepted method in Javascript? frankly looks like ugly hack :-)
zaharpopov
also why you say "do_something" create closure? If I print `this` in do_somethiing I get correct object
zaharpopov
No, its not a hack at all. The only other way is to specifically set what `this` means by binding it to the function. However, in this case, the `arr.sort` method does the calling, and you don't have a chance to set what `this` means. In an object like scenario, I actually declare `var base = this;` at the top, and then only use `base` to refer to that object within the scope of the function. That way, I don't have to guess when to use `this` and when to use `base`.
Doug Neiner
@zaharpopov Also, good catch, I updated my answer. It is not the `do_something` method, it is the anonymous function used to sort. In that context, `this` is probably equal to the Array, but I am not sure.
Doug Neiner
@z: it _is_ a hack, but required due to the incorrect implementation of *this* in the javascript spec. assigning var that = this; in the constructor is the standard method of retaining a valid reference to the object being created.
Sky Sanders
can you point to good articles on this topic?
zaharpopov
A: 

Since your sort algorithm doesn't depend on anything within do_something (other than that provided by the array), consider moving the function outside of do_something:

function some_object(...) {
   var so = this;
   so.data = {...};
   var comparator = function(a,b) { return so.data[a] - so.data[b]; };

   this.do_something = function(...) {
      var arr = [...].sort(comparator);
   }
}

Or, even provide a simple factory if you do this kind of sorting elsewhere:

var comparatorFactory = function(data) { return function(a,b) { return data[a] - data[b]; } };
function some_object(...) {
   var so = this;
   so.data = {...};
   var comparator = comparatorFactory(so.data);
   ...
nicerobot