How do I declare a namespace in JavaScript?

Viewed 616063

How do I create a namespace in JavaScript so that my objects and functions aren't overwritten by other same-named objects and functions? I've used the following:

if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}

Is there a more elegant or succinct way of doing this?

29 Answers

I like this:

var yourNamespace = {

    foo: function() {
    },

    bar: function() {
    }
};

...

yourNamespace.foo();

Another way to do it, which I consider it to be a little bit less restrictive than the object literal form, is this:

var ns = new function() {

    var internalFunction = function() {

    };

    this.publicFunction = function() {

    };
};

The above is pretty much like the module pattern and whether you like it or not, it allows you to expose all your functions as public, while avoiding the rigid structure of an object literal.

I use this approach:

var myNamespace = {}
myNamespace._construct = function()
{
    var staticVariable = "This is available to all functions created here"

    function MyClass()
    {
       // Depending on the class, we may build all the classes here
       this.publicMethod = function()
       {
          //Do stuff
       }
    }

    // Alternatively, we may use a prototype.
    MyClass.prototype.altPublicMethod = function()
    {
        //Do stuff
    }

    function privateStuff()
    {
    }

    function publicStuff()
    {
       // Code that may call other public and private functions
    }

    // List of things to place publically
    this.publicStuff = publicStuff
    this.MyClass = MyClass
}
myNamespace._construct()

// The following may or may not be in another file
myNamespace.subName = {}
myNamespace.subName._construct = function()
{
   // Build namespace
}
myNamespace.subName._construct()

External code can then be:

var myClass = new myNamespace.MyClass();
var myOtherClass = new myNamepace.subName.SomeOtherClass();
myNamespace.subName.publicOtherStuff(someParameter);

I think you all use too much code for such a simple problem. No need to make a repo for that. Here's a single line function.

namespace => namespace.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window);

Try it :

// --- definition ---
const namespace = name => name.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window);

// --- Use ----
const c = namespace("a.b.c");
c.MyClass = class MyClass {};

// --- see ----
console.log("a : ", a);

ES6 Modules Namespace imports

// circle.js
export { name, draw, reportArea, reportPerimeter };
// main.js
import * as Circle from './modules/circle.js';

// draw a circle
let circle1 = Circle.draw(myCanvas.ctx, 75, 200, 100, 'green');
Circle.reportArea(circle1.radius, reportList);
Circle.reportPerimeter(circle1.radius, reportList);

This grabs all the exports available inside circle.js, and makes them available as members of an object Circle, effectively giving it its own namespace.

I've written another namespacing library that works a bit more like packages / units do in other languages. It allows you to create a package of JavaScript code and the reference that package from other code:

File hello.js

Package("hello", [], function() {
  function greeting() {
    alert("Hello World!");
  }
  // Expose function greeting to other packages
  Export("greeting", greeting);
});

File Example.js

Package("example", ["hello"], function(greeting) {
  // Greeting is available here
  greeting();  // Alerts: "Hello World!"
});

Only the second file needs to be included in the page. Its dependencies (file hello.js in this example) will automatically be loaded and the objects exported from those dependencies will be used to populate the arguments of the callback function.

You can find the related project in Packages JS.

In JavaScript there are no predefined methods to use namespaces. In JavaScript we have to create our own methods to define NameSpaces. Here is a procedure we follow in Oodles technologies.

Register a NameSpace Following is the function to register a name space

//Register NameSpaces Function
function registerNS(args){
 var nameSpaceParts = args.split(".");
 var root = window;

 for(var i=0; i < nameSpaceParts.length; i++)
 {
  if(typeof root[nameSpaceParts[i]] == "undefined")
   root[nameSpaceParts[i]] = new Object();

  root = root[nameSpaceParts[i]];
 }
}

To register a Namespace just call the above function with the argument as name space separated by '.' (dot). For Example Let your application name is oodles. You can make a namespace by following method

registerNS("oodles.HomeUtilities");
registerNS("oodles.GlobalUtilities");
var $OHU = oodles.HomeUtilities;
var $OGU = oodles.GlobalUtilities;

Basically it will create your NameSpaces structure like below in backend:

var oodles = {
    "HomeUtilities": {},
    "GlobalUtilities": {}
};

In the above function you have register a namespace called "oodles.HomeUtilities" and "oodles.GlobalUtilities". To call these namespaces we make an variable i.e. var $OHU and var $OGU.

These variables are nothing but an alias to Intializing the namespace. Now, Whenever you declare a function that belong to HomeUtilities you will declare it like following:

$OHU.initialization = function(){
    //Your Code Here
};

Above is the function name initialization and it is put into an namespace $OHU. and to call this function anywhere in the script files. Just use following code.

$OHU.initialization();

Similarly, with the another NameSpaces.

Hope it helps.

JavaScript does not yet have a native representation of namespaces, but TypeScript does.

For example, you could use the following TS code (playground)

namespace Stack {
    export const hello = () => console.log('hi')
}

Stack.hello()

If you can't update your code to TS, you can at least use the pattern employed by TS when generating the JS output for namespaces, which looks like this:

var Stack;
(function (Stack) {
    Stack.hello = () => console.log('hi');
})(Stack || (Stack = {}));
Stack.hello();

Further Reading:

JavaScript doesn’t support namespace by default. So if you create any element(function, method, object, variable) then it becomes global and pollute the global namespace. Let's take an example of defining two functions without any namespace,

function func1() {
    console.log("This is a first definition");

}
function func1() {
    console.log("This is a second definition");
}
func1(); // This is a second definition

It always calls the second function definition. In this case, namespace will solve the name collision problem.

Related