4

Here's a sample of my structure:

this.is.a.really.long.namespace = {

    inputs : {},
    buttons : {},
    panels : {},

    fn : {

        abc : function() {},
        def : function() {}

    } 

};

Now, as you can see I'm storing my inputs, buttons, panels, and functions in their own respective object literals. The issue lies within fn.abc, fn.def, or any other function inside of page.fn. I want to be able to access my inputs, buttons, and panels from within the functions inside of fn.

Obviously, I know I can type this.is.a.really.long.namespace.inputs, but as you can see, that's pretty long, and I don't want to have to type it out for every single instance where I need to reference an object within the page.

Is there not a way I can directly reference inputs, buttons, and panels from within fn?

I was thinking I could do:

fn : {

    that : this.is.a.really.long.namespace,

    abc : function() {},
    def : function() {}

}

which would allow me to use that.inputs inside of fn.abc, but is there a concern with that method? Any sort of overhead I need to be aware of? Or is there a better way to accomplish this?

Code Maverick
  • 20,171
  • 12
  • 62
  • 114

4 Answers4

2

There is nothing wrong with this. In fact you are likely to reduce overhead for the following reasons:

  1. Less run-time resolution of object heirarchies
  2. Fewer characters = shorter script

A more fleshed out construct is the commonly used "module pattern."

Javascript is fairly inefficient internally (e.g. it doesn't have real indexed arrays) so anything you can do to reduce run-time lookups is usually good. Creating a pointer to a long heirarchy will be much faster than using the full heirarchy every time. This will probably only matter much in long loops, but since it's also easier to read, it's just a bonus of being a bit faster - there is no downside.

(edit)

to do this with straight objects you could do something like this, using jQuery to simplify adding properties:

this.is.a.long.namespace = {};
$.extend(this.is.a.long.namespace, 
   { that: this.is.a.long.namespace,
   ... // other properties 
   });

Generally speaking though if you're building functional objects the module pattern is better, because it's more flexible and lets you use scope to create private variable/objects.

this.is.a.long.namespace = (function() 
{
    var that = {},
       somePrivateVariable;
    function privateFunction() {
      ...
    } 
    that.inputs = {};
    ...
    // assign everything to "that"
    return that;
}());
Jamie Treworgy
  • 23,934
  • 8
  • 76
  • 119
  • Well, you can't do what thescientist suggests, and I just tried out my example in my project, and it doesn't work either. First of all, inside of `fn.abc`, I'd have to use `this` to get access to `that`, and if you do `this.that.inputs.whatever` you get an error stating `this.that.inputs` is undefined. – Code Maverick Jun 29 '11 at 19:56
  • Right I misread his post at first. He's confused about a function versus an object definition. You can do it exactly how you have said, though, or use the module pattern to return an object instead in which case you can do it that way. – Jamie Treworgy Jun 29 '11 at 19:59
  • * with one caveat - if the reference is to *itself* then it won't work because it does not exist yet. But you can reference one level up that way, or create a stub for the object first: `this.is.a.long.namespace = {};` then add properites to it, in which case you can add a self reference. – Jamie Treworgy Jun 29 '11 at 20:01
  • See caveat. And see my edit for an easy solution if you're using jQuery. – Jamie Treworgy Jun 29 '11 at 20:05
  • Sorry if you have been watching my frequent edits -- I think the examples are all correct now. – Jamie Treworgy Jun 29 '11 at 20:09
  • Ah I see ... I like that module pattern. Instead of every level being a deeper object literal, they are all functions. I have about 2000 lines to convert if I were to move to that though ... eek. – Code Maverick Jun 29 '11 at 20:10
  • Well, there's always the `$.extend` way if your only need is to add a self-reference, though it's not particularly efficient since it has to copy everything from one object to another. – Jamie Treworgy Jun 29 '11 at 20:13
  • I posted my solution. Thanks for your input though ... I definitely will consider upgrading my current situation to the module pattern. +1 – Code Maverick Jun 29 '11 at 20:24
0

If you build the object in such a way that every level contains a parent parameter pointing to the level above it, then you can access the data that way. Take a look at this similar question.

Community
  • 1
  • 1
hughes
  • 5,595
  • 3
  • 39
  • 55
0

I would consider something like this:

var namespace = this.is.a.really.long.namespace
this.is.a.really.long.namespace = {

    root : namespace,
    inputs : {},
    buttons : {},
    panels : {},

    fn : {

        abc : function() {},
        def : function() {}

    } 
};

from there you should have no problems referencing your namespace anywhere within the object.

thescientist
  • 2,906
  • 1
  • 20
  • 15
0

Ok ... Here's what I ended up doing:

this.is.a.really.long.namespace = {

    inputs  : { firstName : undefined },
    buttons : { submit : undefined },

    fn : {

        root : undefined,

        abc : function() { console.log(this.root.inputs.firstName); },
        def : function() { console.log(this.root.buttons.submit); }

    },

    init : function() {

        var self     = this,
            fn       = self.fn,
            inputs   = self.inputs,
            buttons  = self.button;

            fn.root  = this;  // this is the key

            inputs.firstName  = $("#first-name");
            buttons.submit    = $("#submit-button");

        fn.abc();
        fn.def();

    }

};
Code Maverick
  • 20,171
  • 12
  • 62
  • 114