2

Hello I'm having a problem that haven't searched before

I'm trying to recode my javascript used for accessing google api's so that I can create objects to access them in further projects . Let me Explain the Code because I'm not posting the original code here below code is the just like an example of my code

I'm a having constructor function and it has arrays declared with 'this' keyword. and Then I have an prototype of the constructor function and inside that prototype I had a nameless function created to access jquery requested output from a server.But I'm unable to access those array objects

function cons(){
 this.objectarray = [];
}
cons.prototype.profun = function(){
 this.objectarray[0] = 'working';
 alert(this.objectarray[0]);//Access is possible
 $.get('requesting url',{'parameters'},function(data){
  alert(this.objectarray[0]);//Access is not possible
 });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

when I try to access the object inside that jquery function I'm getting this error from browser console

TypeError: this.YouTubeTitle is undefined
  • Possible duplicate of [How do JavaScript closures work?](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Björn May 29 '17 at 18:55
  • If you want to use `this` within the callback function, you had better [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) that callback to `this` (see @Björn's closures link for alternatives) – James May 29 '17 at 18:58
  • The `this` floats to whomever invokes the callback function. So you might also try [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)ing the callback function like `function(data){alert(this.objectarray[0]);}.bind(this)` – Redu May 29 '17 at 22:11
  • I doesn't know if linked closures have solution or not but this `function(data){alert(this.objectarray[0]);}.bind(this)` worked thank you @Redu for the solution – DevelopersWork May 30 '17 at 03:23

4 Answers4

2

You have to cache the this object so that when you use the this keyword in your callback, it refers to the correct object:

function cons(){
 this.objectarray = [];
}
cons.prototype.profun = function(){
  // this is volatile in JavaScript. It's meaning changes depending
  // on the invocation context of the code that contains it. Here,
  // this will refer to your "cons" object instance.
  var self = this;

 this.objectarray[0] = 'working';
 alert(this.objectarray[0]);
 $.get('requesting url','parameters',function(data){
    // But here, "this" will be bound to the AJAX object
  alert(self.objectarray[0]);  // <-- Use cached this object
 });
};

//*************************

var c = new cons();
c.profun();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • @DevelopersWork The code snippet here certainly is working. – Scott Marcus May 30 '17 at 03:30
  • sorry @scott it's working I forgot to declare the self variable thanks for the answer – DevelopersWork May 30 '17 at 05:01
  • @DevelopersWork if it is working you should accept this answer as the solution to your question :-) – Björn May 30 '17 at 08:00
  • 1
    @Björn I accepted the solution but creating another variable can take more memory but rather I use `bind` option to bind `this` to the `callback` – DevelopersWork Jun 01 '17 at 15:18
  • 1
    @Björn An object variable takes roughly 2 bytes of memory, which is absolutely nothing. `bind` returns a new function that also must be stored and will take more than 2 bytes to store. Both solutions will have zero actual impact on performance, but `bind` is more involved for no real benefit. – Scott Marcus Jun 01 '17 at 16:45
  • @DevelopersWork I do not mind which answer you accept or use. I just wanted to be helpful in reminding you of closing this thread by marking a solution. :-) Cheers. – Björn Jun 02 '17 at 07:24
1

Inside the GET-Callback there is a local this which overrides your Prototype-Function's this. Store the outer this in a named variable and call that inside the callback and you will be fine.

let outerThis = this;
somethingWithCallback(function(){
  alert(outerThis);
})
Björn
  • 471
  • 10
  • 15
1

I've found solution for this from one of the comments

the below code is the solution

function cons(){
 this.objectarray = [];
}
cons.prototype.profun = function(){
 this.objectarray[0] = 'working';
 alert(this.objectarray[0]);
 $.get('requesting url',{'parameters'},function(data){
  alert(this.objectarray[0]);
 }.bind(this));//by binding 'this' we can access the 'objectarray'
}

Thanks for the solution @Redu from comments

0

You can wrap your anonymous function with $.proxy to persist the outer this context.

function cons() {
  this.objectarray = [];
}
cons.prototype.profun = function() {
  this.objectarray[0] = 'working';
  alert(this.objectarray[0]);
  $.get('requesting url', {
    'parameters'
  }, $.proxy(function(data) {
    alert(this.objectarray[0]);
  }, this));
}
Karen Grigoryan
  • 5,234
  • 2
  • 21
  • 35