0

I want to namespace some functions within MyNamespace. I figured first I would make an object MyNamespace, and then define functions in it.

How can I assign functions to a namespace while still using the form function myThing() {...}? What would this syntax look like?

Object syntax that won't work:

var MyNamespace = {
  function helloWorld() {
    console.log('hi!');
  }

  function goodbyeWorld() {
    console.log('I <3 Titanic');
  }
}

MyNamespace.helloWorld();

Object syntax that will work, but doesnt use the function() {} syntax

var MyNamespace = {
  helloWorld: function() {
    console.log('hi!');
  },

  goodbyeWorld: function() {
    console.log('I <3 Titanic');
  }
}

MyNamespace.helloWorld();

Maybe I can do function MyNamespace.helloWorld() {...} but this doesnt seem to work.

Don P
  • 60,113
  • 114
  • 300
  • 432

2 Answers2

4

Your second example is the most commonly-used way. There's no technical advantage to having "function name()" in that order. There is another alternative:

function wrapper() {
  function helloWorld() {
  }

  function privateFunction() { }

  return {
    helloWorld: helloWorld
  };
}

In that instance, you can also declare namespace-private functions like the one there. helloWorld could call privateFunction, but nothing outside can directly call it. (Note that all public functions will need to be in that returned object)

To auto-instantiate:

// in the ... insert my above example
window.mynamespace = (...)();
Katana314
  • 8,429
  • 2
  • 28
  • 36
  • Nice Katana - and that would still let me directly call `wrapper.helloWorld()` without first having to instantiate wrapper? – Don P Jul 10 '14 at 20:32
  • @DonnyP With an assignment and `wrapper` as an [IIFE](http://stackoverflow.com/questions/8228281/what-is-this-iife-construct-in-javascript), sure. [Revealing Module Pattern](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript). – Jonathan Lonowski Jul 10 '14 at 20:39
2

You can either declare them in the original object like you did here:

var MyNamespace = {
  helloWorld: function() {
    console.log('hi!');
  },

  goodbyeWorld: function() {
    console.log('I <3 Titanic');
  }
}

MyNamespace.helloWorld();
MyNamespace.goodbyeWorld();

Or, you can declare the namespace and then add the methods afterwards like this:

// declare namespace object
var MyNamespace = {};

// add methods to the namespace
MyNamespace.helloWorld = function() {
    console.log('hi!');
};

MyNamespace.goodbyeWorld = function() {
    console.log('I <3 Titanic');
};

MyNamespace.helloWorld();
MyNamespace.goodbyeWorld();

This lets you add methods to the namespace in different places or even in different source files.


And, if you want to have some private, but static variables, you can use an IIFE (immediately invoked function expression) to encapsulate those variables like this:

var MyNamespace = (function() {

  var privateCntr = 0;

   return {
       getUniqueCnt: function() {
           return ++privateCntr;
       },

       goodbyeWorld: function() {
           console.log('I <3 Titanic');
       }
   };
})();

var uniqueID = MyNamespace.getUniqueCnt();
MyNamespace.goodbyeWorld();

All three options accomplish the same goal. The third option gives you the option of private variables (which the other two do not) and you can also use the second method to add on more methods after declaring the namespace in any of the other ways (though methods you add outside the IIFE won't have access to the private variables).

If I need any private variables, I use the third option.

If I don't have any need for private variables and I'm going to define all the methods in one place, I prefer the first option as it just seems to be more obvious what you're doing - you're declaring an object with a bunch of methods and all the methods are declared in one place.

If I'm adding methods across multiple files and don't need any private variables, I will use the second option.

jfriend00
  • 683,504
  • 96
  • 985
  • 979