1

I have a javascript class declared as shown below.. My problem is the aonymous function does not see the scope of the class. I can not reference the bb_obj from within the ajax call load callback..

Is there a way to do this?

Thanks in advance..

dojo.declare("sop.quote", null,
{
   bb_obj : new Object,

   stage1 : function()
   {
      dojo.xhrPost(
      {
         url      :  'go/module_service/transport.php',
         content  :  this.bb_obj,
         handleAs :  'xml',
         load     :  function(xml)
         {
            var status  = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
            var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue; 

            this.bb_obj.message = message;
         },
         error    : function()
         {
         }
      }
   }
}
Lee
  • 5,816
  • 6
  • 45
  • 61

2 Answers2

2

this inside a XHR callback function refers to the XHR object. The only way to refer to bb_obj is by directly referring to the created object, in the same scope as the function. Because objects are passed by reference, the code below works as intended.

Note to avoid confusion, I've declared the object using var bb_obj_obj={}. The bb_obj property refers to bb_obj_obj:

  • bb_obj_obj.message is changed
  • bb_obj points to bb_obj_obj, hence bb_obj.message refers to the same variable

Code:

var bb_obj_obj = {}; //new Object
dojo.declare("sop.quote", null,
{
   bb_obj : bb_obj_obj,

   stage1 : function()
   {
      dojo.xhrPost(
      {
         url      :  'go/module_service/transport.php',
         content  :  this.bb_obj,
         handleAs :  'xml',
         load     :  function(xml)
         {
            var status  = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
            var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue; 

            bb_obj_obj.message = message; //Without `this`
         },
         error    : function()
         {
         }
      }
   }
}

An alternative method consists of saving this in a variable, eg. $this:

...
stage1 : function()
{
    var $this = this;
    dojo.xhrPost({
     ...
     load     :  function(xml){
        var status  = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
        var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue; 

        $this.bb_obj.message = message; //Using `$this` instead of `this`
     },
...
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Or create a reference to `this` first: `var self = this;`. – Felix Kling Oct 20 '11 at 10:42
  • more specific: within `stage1 : function () {` the very first line should be `var self = this;` and then you could do `content : self.bb_obj`. And this is better than solution proposed in answer above. – Misha Reyzlin Oct 20 '11 at 10:46
  • @gryzzly Don't use `self`. `self` is already defined to hold the value of the current `window` object. – Rob W Oct 20 '11 at 10:48
  • @RobW in dojo? strange, I think `global` should be used to store reference to `window`. Anyway, then use `that` perhaps. I personally don't like `$this`. Prefixing a name with `$` is a convention to highlight `jQuery` object (hungarian notation which I dislike too), so it might be confusing. Using `that` was popularized by Crockford, so perhaps it's a good idea to use it. (My personal preference is `self` but if it's already taken I'd use `that`). – Misha Reyzlin Oct 20 '11 at 13:21
0

The typical Javascript practice, in this case, is to wrap the whole thing in an an unnamed function. All local variables of this function will be accessible to every object/function declared therein. By immediately calling this unnamed function you make sure the code inside the function gets executed.

(function() {
 var bb_obj = {}

 dojo.declare("sop.quote", null,  {
   stage1 : function()
   {
      dojo.xhrPost(
      {
         url      :  'go/module_service/transport.php',
         content  :  this.bb_obj,
         handleAs :  'xml',
         load     :  function(xml)
         {
            var status  = xml.getElementsByTagName("STATUS")[0].childNodes[0].nodeValue;
            var message = xml.getElementsByTagName("MESSAGE")[0].childNodes[0].nodeValue; 

            bb_obj.message = message;
         },
         error    : function()
         {
         }
      }
   }
})() 
Itay Maman
  • 30,277
  • 10
  • 88
  • 118
  • 1
    Syntax error: `function(){}()` should at least be written as: `(function(){})()`. Also, the closure doesn't matter, because `bb_obj` is not prefixed by `var`. – Rob W Oct 20 '11 at 11:17