0

I want to setup nested namespaces to organize my code. I am trying to follow the plugin-like structure described in this article. The problem is I don't understand how to access this.error_msg in my example. Have I set this up correctly? Would I have to use jQuery .extend or .prototype to access this.error_msg?

(function(TC, $, undefined){

    TC.ajax = function() {
        this.error_msg = 'default error...';         
    };

    TC.ajax.run = function(){
        //do stuff...
        TC.ajax.handle_error();
    };

    TC.ajax.handle_error = function(){
        alert(this.error_msg);
    };        

}(window.TC = window.TC || {}, jQuery));

// Test it
TC.ajax.run();

Demo: http://jsfiddle.net/g99yt/

5 Answers 5

3

The important thing to remember is that each time you use function(), you are creating a new scope. So you can see that in your TC.ajax.handle_error method that this.error_msg is undefined because you haven't defined it in that scope. One thing you can do is prototype to make sure those methods relate back to your ajax object and declare a new instance of the object, and then call your methods on that. see below :

(function(TC, $, undefined){

    TC.ajax = function() {
        this.error_msg = 'default error...';         
    };

    TC.ajax.prototype.run = function(){
        //do stuff...
        this.handle_error.call(this);
    };

    TC.ajax.prototype.handle_error = function(){
        alert(this.error_msg);
    };        

}(window.TC = window.TC || {}, jQuery));

// Test it
 var ajaxInstance = new TC.ajax();

ajaxInstance.run();

and the fiddle

you do have other options like keeping a locally global variable like @kta does, or by setting your scope through the call function, but that doesn't really apply well to your structure.

Sign up to request clarification or add additional context in comments.

2 Comments

This maintains scope well unlike the other solutions. It sucks to add the step of having to create an instance, but I understand why that is required.
glad I could help. it's probably a good idea to get into the practice of creating instances if you plan on getting into more indepth object oriented javascript
2

I think your code must look something like this:

(function(TC, $, undefined){
    _this = this;
    TC.ajax = function() {
        _this.error_msg = 'default error...';         
    };

    TC.ajax.run = function(){
        //do stuff...
        TC.ajax.handle_error();
    };

    TC.ajax.handle_error = function(){
        alert(_this.error_msg);
    };        

}(window.TC = window.TC || {}, jQuery));

// Test it
TC.ajax.run();

1 Comment

This works but I am trying to avoid error_msg being global (under TC) in scope. I want it only accessible from TC.ajax and functions nested below that. So when I wrote this.error_msg what I meant was TC.ajax.error_msg. So far it looks like I'd need to use prototype for this, as described by Evan... Unless you know another way?
0

If TC.ajax is supposed to be a constructor, then run() and handle_error() need to be added to a prototype.

But you could do something like

TC.ajax = {};    
TC.ajax.error_msg = 'default error...'; 

In your case error_msg will be assigned to this as soon as you call TC.ajax(), which never happens. And even then, this would refer to TC. And when TC.ajax.handle_error()is called, this refers to TC.ajax.

Comments

0

It's actually a common problem, it's not immediately clear what this refers to. So to explain:

TC.ajax.handle_error = function(){
    alert(this.error_msg);
};   

The this in the TC.ajax.handle_error function refers to the function and not your TC object. So just save the reference to TC so you can refer to it later:

var _this = this;

...
_this.error_msg = 'default error....';
...

TC.ajax.handle_error = function(){
     alert(_this.error_msg);
 };        

2 Comments

Hmmm, but I am trying to reference TC.ajax.error_msg, not TC.error_msg. How would this apply to that scope?
@Justin Sorry I'll clarify the answer, TC has error_message as a property, so having that reference to TC allows you to access TC.error_msg.
0

This is what I ended up using:

(function ($, TC, undefined) {

    TC.nestedNamespace = TC.nestedNamespace || {};

    //add a public function to our new namespace 
    TC.nestedNamespace.test = function () {        
       console.log("Winning!");    
    };

}(jQuery, window.TC = window.TC || {}));

TC.nestedNamespace.test();

Example JSFiddle. I found this method in the comments of a related article.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.