7

one of my classes in Javascript needs to be "updated" with Json sometimes. I have always done a function, that updates the array of data, given an id, but now i wanted to do it more encapsulated (Function update, inside the class).

What i made:

function File(data){
        this.data = data;

        this.update = function (callback){
            var set = function(ajaxData){
                this.data = ajaxData.PcbFile;
            }
            getPcbFile(data.id, function(ajaxData){
                set(ajaxData);
                callback();
            });
        };
    }

But, this.data = ajaxData.PcbFile; doesen't work... My object still with the last data set, and not the updated one. The function SET, i created as another attempt to set the data.

There is no problem on the ajax, since i debuged the ajaxData, and it's ok (when i update).

So, how do i really access the object property data from an inside function?

(sorry for my english...)

Ivan Seidel
  • 2,394
  • 5
  • 32
  • 49
  • The value that "this" is resolved to **depends on the way you call the function** that contains whatever code makes use of it. Check out the [MDN docs for this](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this). – Alexander Aug 06 '12 at 03:38

4 Answers4

21

I learned this the hard way, you have to be careful with this. It always refers to the this in the current scope, not it's containing object. Whenever you wrap something in function() { ... }, this becomes of a different scope. In your case, duplicate the object to a local variable and manipulate it's .data property.

function File(data){
    this.data = data;
    var file = this; //call the variable whatever you want
    this.update = function (callback){
        var set = function(ajaxData){
            file.data = ajaxData.PcbFile;
        }
        getPcbFile(data.id, function(ajaxData){
            set(ajaxData);
            callback();
        });
    };
}
Polyov
  • 2,281
  • 2
  • 26
  • 36
  • _"It always refers to the current scope"_ - Except when it doesn't. You can explicitly set `this` to whatever object you like if you call a function with `.apply()` or `.call()`. – nnnnnn Aug 06 '12 at 03:42
  • @nnnnnn yes, but i've never used that or ever seen it used. it seems like an outlandishly advanced way to solve the problem. – Polyov Aug 06 '12 at 04:29
  • Well I wouldn't use `.apply()` or `.call()` for the problem at hand (you can see my answer is essentially the same as yours), but I have used them for other cases. I was just being picky about the language you used - note that `this` refers to an object, which isn't the same as scope. – nnnnnn Aug 06 '12 at 04:45
  • While I understand that what "this" is referencing changes in the new scope, and therefore copying "this" into "thing" works, if my new "this" has changed in the new scope, my old "this" should still be accessible because it's within the "old" this's scope. So I can't use "this" to reference old "this" but I believe the original question was "how can I reference 'old' this"? If this was a class inheriting from another class I might use super.memberName. So the question is, can I access my higher level members without creating a copy? – Gary Richter Oct 01 '15 at 21:44
8

Cache this so you can refer to it in the same context some place else:

function File(data){

  var self = this;

  self.data = data;

  self.update = function (callback){
    var set = function(ajaxData){
      self.data = ajaxData.PcbFile;
    }
    getPcbFile(data.id, function(ajaxData){
      set(ajaxData);
      callback();
    });
  };
}
elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • 1
    +1. Nice to see somebody else using `self` to reflect that the variable actually is a reference to self, instead of the common but (in my opinion) horrible `that`, which always sounds like it should refer to some _other_ object. Or, with apologies to SomekidwithHTML, `thing`, which doesn't really mean anything at all... – nnnnnn Aug 06 '12 at 03:45
  • I mainly use `self` because it gets highlighted as keyword in most editors, much easier to track but I agree that `that` is more common but less semantic. – elclanrs Aug 06 '12 at 03:48
  • @nnnnnn i don't think it really matters; you'd only have to keep track of the variable in the scope you are using it in. However, `self` is definitely better than `thing`, i agree. – Polyov Aug 06 '12 at 04:32
1

Try this:

function File(data){
    this.data = data;

    var self = this;

    this.update = function (callback){
        var set = function(ajaxData){
            self.data = ajaxData.PcbFile;
        }
        getPcbFile(data.id, function(ajaxData){
            set(ajaxData);
            callback();
        });
    };
}

The value of this within a function depends on how that function is called. E.g., when you use the "dot" notation, someObj.someMethod() then within someMethod() you'd have this set to someObj. You can explicitly set this to some other object using the .apply() or .call() methods. Otherwise if you call a function as with set(ajaxData) then this will be the global object (window).

By keeping a reference to this outside your function (I prefer the variable name self for this purpose) you can reference it inside your function.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
0
 (function(){
   var accessible = {
     prop1: 'blabla',
     verify: function(){
       console.log( this.prop1);
       return this;
     },
     deepAccess: function(){
       return function(){
         accessible.prop1 = 'bloblo';
         return function(){
           console.log("Deep access ", accessible.prop1);
         }
       }
     },
     insideFunction: function(){
       //here you can use both 'this' or 'accessible' 
                  this.prop1 = 'bleble';
                  return this;
       },
       prop2: 3.1415
    };
   return accessible;
})().verify().insideFunction().verify().deepAccess()()();

/* console shows:
 blabla
 bleble
 Deep access bloblo
*/
Sergio Abreu
  • 2,686
  • 25
  • 20