Fletcher Moore
Fletcher Moore

Reputation: 13814

How do you add objects to a javascript namespace?

var Test = (function() {
    return {
        useSub: function () {
            this.Sub.sayHi();
        },

        init: function () {
            $(document).ready(this.useSub);
        }
    };
})();

Test.Sub = (function () {
    return {
        sayHi: function () {
            alert('hi');
        }
    };
})();

Test.useSub(); // works
Test.init(); // explodes

Above I am trying to create a Test namespace and add an object Sub to it. I was doing fine until I tried using the object in jQuery. The error is "Uncaught TypeError: Cannot call method 'sayHi' of undefined". If there is a better way to do this, I am open to it.

Edit:

Obviously this was demo code. In my real application the solution that I went with because I think it is the most clear is this one:

var Namespace (function () {
  return {
    init: function () {
      $(document).ready(function() {
        Namespace.onReady();
      }
    },
    onReady: function() {
      alert('Now I am back in the Namespace scope. Proceed as planned');
    }
  };
})();

Edit2: All jQuery callbacks seem to require they are used in this manner or else the scoping is screwed up.

Upvotes: 1

Views: 678

Answers (3)

John Hartsock
John Hartsock

Reputation: 86892

Here is one way

var Test = {
  useSub : function () { 
    Test.Sub.sayHi(); 
  }, 
  init: function () { 
    $(document).ready(Test.useSub); 
  },
  Sub: {
    sayHi: function () { 
      alert('hi'); 
    } 
  }
};

Upvotes: 2

Felix Kling
Felix Kling

Reputation: 816930

I think it is a scope problem. If you do

$(document).ready(this.useSub);

then this.useSub will be executed in the window scope (so inside the function, this refers to the window object) and there doesn't exist a Sub attribute.

Try:

init: function () {
    var obj = this;
    $(function(){obj.useSub()});
}

For some reason it does not work using $(document).ready(function(){obj.useSub()}); but it works with the $() shortcut.

Upvotes: 5

lincolnk
lincolnk

Reputation: 11238

in this line:

$(document).ready(this.useSub);

you're passing a reference to a function and the scope is lost- when the function runs, this no longer means Test.

Upvotes: 1

Related Questions