access outer "this" in Javascript sort method

Viewed 12634

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

4 Answers

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];
      });  
   }
}

I know this is a question from 2010, but now you should probably use arrow functions (and classes):

class some_object {
  constructor() {
    this.data = {...};
  }
  do_something(...) {
    let arr = [...];
    arr.sort((a, b) => this.data[a] - this.data[b]);
  }
}

Arrow functions don't have a this, so they use the one from the enclosing scope.

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);
   ...
Related