0

I'm trying to create nested class definitions in javascript to have only one global object.

At the moment we define new classes like this:

FOO.Navigation.Sidebar.Tooltip = function()
{
};

So in each function definition we have to repeat the whole nested class namespace:

FOO.Navigation.Sidebar.Tooltip.prototype.show = function()
{
  /* do something here */
};

We introduced a namespace function to create the class.

FOO = { /* ... */ }

FOO.namespace = function(namespaceString)
{
  var namespaceParts = namespaceString.split('.');
  var currentRoot = FOO;
  var index = 0;

  // Skip the first namespacePart, if it is already "FOO"
  if ("FOO" == namespaceParts[0])
  {
  index = 1;
  }

  var currentPart;  
  for(index; index < namespaceParts.length; index++)
  {     
    // This is the next element in the namespace hierarchy.
    currentPart = namespaceParts[index]; 
    // Add a new map for the currentPart to the root (if it does not exist yet). 
    currentRoot[currentPart] = currentRoot[currentPart] || {};
    // The currentPart will be the new root in the next loop.
    currentRoot = currentRoot[currentPart];
  }

  return currentRoot;
};

Now we want to use this to create a more readable version of previous definitions which should look like this:

FOO.Navigation.Sidebar.Tooltip = function()
{
  this.hallo = "world";
};

var tooltip = FOO.Navigation.Sidebar.Tooltip;

tooltip.prototype.show = function()
{
  /* do something */
};

That would create a new global variable "tooltip" and we have to type the class name twice. So we thougth of using anonymous functions like this:

(function(tooltip) {
  tooltip = function()
  {
    this.hello = "world";
  };

  tooltip.prototype.show= function()
  {
    /* do something */
  };
}) (FOO.namespace("FOO.Navigation.Sidebar.Tooltip"))

This obviously don't work, because we assing a new function definition to "tooltip".

So my question is, if there is a way to write the class name only once without creating any more global variables.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Stefan Ramson
  • 531
  • 1
  • 6
  • 18
  • I'd remind you that you're writing JavaScript, not Java. All this `foo.bar.baz.trev.cat.mouse` namespace malarkey doesn't belong in JavaScript. – Matt Apr 05 '12 at 09:40
  • Well, we are trying to make the framework more accessible for our C++ developers. That's why we try to avoid for example additional global variables and so on. – Stefan Ramson Apr 05 '12 at 09:43

1 Answers1

0

It looks to me like you are trying to create an implementation of the Module Pattern. Modules are generally used to create single instance objects; however you can easily add factory methods to the Module which return new closures (functions).

With the code you pasted above you are able to directly attach methods to the supplied tooltip variable inside the closure; for example:

(function(Tooltip) {
    // 'Static' method added to the module definition.
    Tooltip.hello = function() { 
        alert("Hello!");
    };

    // Factory method which returns a new object.
    Tooltip.create(message) {
        return { 
            this.message = message;
            this.show = function() { /* ... */ }
        };
    }
})(FOO.namespace("FOO.Navigation.Sidebar.Tooltip"));

Then you can invoke the hello method on Tooltip:

// Invoke a static method.
FOO.Navigation.Sidebar.Tooltip.hello();​

// Create a new ToolTip instance.
var myToolTip = FOO.Navigation.Sidebar.Tooltip.create("Hello World");
myToolTip.show();

If you want to create a hierarchical class structure then you might want to consider one of the common JavaScript libraries such as Backbone.js

JonnyReeves
  • 6,119
  • 2
  • 26
  • 28
  • Yeah, you're right, but what did not work like this is defining the contructor. – Stefan Ramson Apr 05 '12 at 09:49
  • Hi Stefan, I've updated my answer to include reference to the Module Pattern and adding factory methods. It sounds to me that you might be better served by a more classic OOP design (which some say goes against JavaScript's language). – JonnyReeves Apr 05 '12 at 09:56