How do I declare a namespace in JavaScript?
Solution 1
I like this:
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();
Solution 2
I use the approach found on the Enterprise jQuery site:
Here is their example showing how to declare private & public properties and functions. Everything is done as a self-executing anonymous function.
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "\t\n Butter \n\t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
So if you want to access one of the public members you would just go skillet.fry()
or skillet.ingredients
.
What's really cool is that you can now extend the namespace using the exact same syntax.
//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
The third undefined
argument
The third,
undefined
argument is the source of the variable of valueundefined
. I'm not sure if it's still relevant today, but while working with older browsers / JavaScript standards (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variableundefined
is writable, so anyone could rewrite its value. The third argument (when not passed a value) creates a variable namedundefined
which is scoped to the namespace/function. Because no value was passed when you created the name space, it defaults to the valueundefined
.
Solution 3
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.
Solution 4
Is there a more elegant or succinct way of doing this?
Yes. For example:
var your_namespace = your_namespace || {};
then you can have
var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg)
{
alert(arg);
};
with(your_namespace)
{
Bar(Foo.toAlert);
}
Solution 5
I normally build it in a closure:
var MYNS = MYNS || {};
MYNS.subns = (function() {
function privateMethod() {
// Do private stuff, or build internal.
return "Message";
}
return {
someProperty: 'prop value',
publicMethod: function() {
return privateMethod() + " stuff";
}
};
})();
My style over the years has had a subtle change since writing this, and I now find myself writing the closure like this:
var MYNS = MYNS || {};
MYNS.subns = (function() {
var internalState = "Message";
var privateMethod = function() {
// Do private stuff, or build internal.
return internalState;
};
var publicMethod = function() {
return privateMethod() + " stuff";
};
return {
someProperty: 'prop value',
publicMethod: publicMethod
};
})();
In this way I find the public API and implementation easier to understand. Think of the return statement as being a public interface to the implementation.
Comments
-
Scott McKenzie over 2 years
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?
-
annakata about 15 yearsI can see where you're going with the checking to see if the namespace is taken, but since the object will not be created if this fails I think the better approach is to alert if the namespace is taken. Frankly this should just not happen in most JS situations and should be caught quickly in development.
-
Admin almost 14 yearsTake a top-level "namespace" (window property). Own it. Conflicts should be detected early on in testing. Don't bother adding all these "what if" checks. It's a fatal issue for duplicate "namespaces" and should be treated as such. You can follow an approach like jQuery to allow inhabiting a custom "namespace"; but this is still a design-time issue.
-
Matt about 12 yearssee also stackoverflow.com/questions/2102591/… for performance issues
-
Matt about 12 yearssee also stackoverflow.com/questions/4125479/… for object vs function namespaces
-
Justin almost 11 yearsThis is a ton of information, but really lays out the differences amongst the different JS design patterns. It helped me a lot: addyosmani.com/resources/essentialjsdesignpatterns/book
-
Sebastian Simon almost 3 yearsMeh, nowadays we have symbols and modules, so duplicate namespaces shouldn’t even be an issue.
-
-
annakata about 15 yearsIt's kind of blindsided me that anyone wouldn't love OLN. I just... what's not to love? What's so rigid?
-
annakata about 15 yearsThe important point is to be religious about expanding no further than the one root variable. Everything must flow from this.
-
user5880801 about 15 years1. There's a difference between OLN and the module pattern. 2. I don't /always/ like OLN as you have to remember to not put the last trailing comma and all your attributes must be initialized with a value (like null or undefined). Also, if you need closures for member functions, you will need small function factories for each of those methods. Another thing is that you must enclose all your control structures inside functions, whereas the above form does not impose that. That's not to say that I don't use OLN, is just that sometimes I don't like it.
-
Hungry Beast about 14 yearsThe syntax of this approach really bothers me. I hate not ending lines with a semicolon and in this solution declaration order matters. I do still think it's a completely valid and in cases a good solution. How do you do callback functions on a JQUery call with this approach?
-
mckoss almost 14 yearsI've created an improved version (2.0) of the namespace library: code.google.com/p/pageforest/source/browse/appengine/static/src/…
-
Titi Wangsa bin Damhore over 13 yearsthis style is compatible with my javascript editor (eclipse), as in, it can do auto formatting and indentation.
-
Lawrence Barsanti over 13 yearsI like this approach because it allows for private functions, variables, and pseudo-constants (i.e. var API_KEY = 12345;).
-
John over 13 yearsGreat detail! Thanks! Just wondering what's your take on Namespace.js. I've never used it myself, so I'm wondering if someone with your knowledge/skill/experience would consider using it.
-
mjallday over 13 yearsthis gives me an error in IE7. var your_namespace = (typeof your_namespace == "undefined" || !your_namespace ) ? {} : your_namespace ; works better.
-
Lucent over 13 yearsI like this better than the comma separated object container that's voted higher. I don't see any shortcomings in comparison, either. Am I missing something?
-
Carles Barrobés over 13 yearsI have a problem making this kind of namespace work with IE7, as posted here: stackoverflow.com/questions/4492372/… - not sure whether it has anything to do with the namespace declaration though. It works fine in all "standard" browsers including IE8
-
yoosiba over 13 yearsI like it! On the other hand I get exception on first line of this external code, saying: 'myNameSpace.MyClass' [undefined] is not constructor. maybe it depends in JS implementation? :/
-
AnthonyWJones over 13 years@yossiba: Possibly. The code above is fairly standard stuff. In standard JS any function can be used as a constructor, there is nothing you need to do to mark a function as specifically for being used as a constructor. Are you using an unusual flavor like ActionScript or something?
-
Palo over 13 yearsit should be var your_namespace = your_namespace = your_namespace || {} Works in every browser ;)
-
mckoss over 13 yearsThis does not create a closure for your code - it makes it tedious to call your other functions because they always have to look like: yourNamespace.bar(); I made an open source project JUST to address this design problem: github.com/mckoss/namespace.
-
Omu over 13 yearsanybody knows why jQuery is not using this approach but the comma separated ?
-
user5880801 over 13 yearsThis pattern works for singleton objects, but
jQuery
is a constructor function. In my example you can't callns()
, and jQuery needs this. -
user406905 about 13 yearsannakata: "The important point is to be religious about expanding no further than the one root variable."- Why is this?
-
Adi Roiban about 13 yearsNow if JSLint would not complain about this legit structure everything will be so much better :)
-
paul almost 13 years@Anthony its better to use var MYNAMESPACE = MYNAMESPACE || {}; just using var myNamespace = {} is unsafe and moreover its better to declare your namespace in caps
-
AnthonyWJones almost 13 years@paul: "Better" can be quite subjective. I hate reading code that SHOUTS at me so I avoid using identifiers that use all uppercase. Whilst
ns = ns || {}
might seem more defensive it can lead to other unexpected results. -
paul almost 13 years@Anthony its just an suggestion and following the conventions. Moreover, its all about your personal preference.
-
John Kraft almost 13 yearsJS Newbie here... why is it that I don't have to type
ns().publicFunction()
, that is...ns.publicFunction()
works. -
user5880801 almost 13 years@John Kraft, it's necause of the
new
keyword in front of thefunction
keyword. Basically, what is doing is that it's declaring an anonymous function (and as a function, it is as well a constructor), and it then immediately invokes it as a constructor usingnew
. As such, the final value that gets stored insidens
is an (unique) instance of that anonymous constructor. Hope it makes sense. -
Darren Lewis almost 13 years+1 for this great sample. For anyone interested, this sample was part of Elijah Manor's excellent presentation at Mix 2011 (ignore the title) live.visitmix.com/MIX11/Sessions/Speaker/Elijah-Manor
-
BumbleB2na almost 13 yearskind of a gotchya with this approach: if you want to access 'public' members or methods within an 'internal' method, you have to add on the 'class' name. Example: ns.publicFunction(); or ns.publicMember;
-
SamStephens almost 13 yearsAs long as you remember this has some performance implications, as each time you access my.awesome.package.WildClass you're accessing the awesome property of my, the package property of my.awesome, and the WildClass property of my.awesome.package.
-
Jared Beck over 12 yearsFrom Elijah's article, here are the pros and cons of this approach, paraphrased. Pros: 1. Public and private properties and methods, 2. doesn’t use cumbersome OLN, 3. Protects undefined 4. Ensures that $ refers to jQuery, 5. Namespace can span files, Cons: Harder to understand than OLN
-
user3167101 over 12 years@user406905: Because then you'd have two global identifiers, everything should live under the one namespace.
-
Antoine over 12 yearsExcellent. But it fails if jQuery is not already loaded. Is there a way to execute anyway, and in there to test for it and load if necessary?
-
natlee75 over 12 years@alex: I can't speak for user406905, but my interpretation of what annakata said is that you should have the one "level" of properties and methods underneath the root namespace. In other words, do me.myselfAndI rather than me.myself.and.i so you have as shallow an object structure as possible. Of course I might have misinterpreted this.
-
Ryan over 12 years@Antoine - Why would it fail? jQuery should be the dependency and should be loaded preceeding your script
-
Antoine over 12 years@Ryan: I'm calling this from a bookmarklet where I don't test for jQuery (want to keep the bookmarklet as simple as possible, logic is done server-side). I overcame this by removing the $ parameter, and testing/loading for jQuery inside the namespace.
-
Ryan about 12 years@alex - why should there be a shallow object structure?
-
user3167101 about 12 years@Ryan I meant that everything should be under
MyApp
, e.g.MyApp.Views.Profile = {}
rather thanMyApp.users = {}
andMyViews.Profile = {}
. Not necessarily that there should only be two levels depth. -
Flash almost 12 yearsAlso worth mentioning that in the above examples
this
refers to what you would expect inpublicFunction
, but refers to the global object ininternalFunction
. I usually addvar self = this
at the top to avoid confusion. -
Gustavo Gondim over 11 yearsThis is called today IIFE (Immediately Invoked Function Expression). Thanks for your answer +1!
-
Gustavo Gondim over 11 years@CpILL the third ùndefined` argument is for ensure that no else function will pass a third argument and will modify the behavior. It is a guaranty.
-
centurian about 11 years+1 from me! Thin one works as Jaco Pretorius answer by expanding one library to different files or different places inside the same file. Just brilliant!
-
mrówa about 11 years@CpILL: not sure if still relevant, but the third,
undefined
argument is source of the variable of valueundefined
. While working with older browsers / javascript standard (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variableundefined
is writable, so anyone could rewrite its value. Adding third, additional argument you are not passing makes it valueundefined
, so you were creating namespace-scopeundefined
which won't be rewritten by outside sources. -
Sriram about 11 years@Palo Can you please explain why it should be like this?
var your_namespace = your_namespace = your_namespace || {}
-
SapphireSun almost 11 yearsSo I don't really understand the purpose of window.skillet = window.skillet || {}. Why would you want another file to accidentally append to the definition of skillet? Wouldn't you rather it did so intentionally? I'd rather see a big bug pop up.... Perhaps it's for when people want to add extensions to your module but you don't know which one is loading first?
-
Jay Sullivan almost 11 years@SapphireSun: Who said it had to be by accident? The syntax allows you to extend the class in multiple places.
-
Laoujin almost 11 yearsIf you feel confused, @Jared Beck presented an excellent pro/con breakdown of the article. Perhaps one additional Con: Don't use this just because it's better. The { } OLN (Object Literal Notation) as explained in the accepted answer is perfect for simple scenarios.
-
Brett Ryan over 10 years@AnthonyWJones, apart from mistakenly using an unintended variable, what unexpected results do you anticipate with
ns = ns || {}
? A more defensive approach could bevar n = n && n.name === "NSNAME" ? n : { name: "NSNAME"};
-
Mark Amery about 10 years@SapphireSun The benefit of
window.skillet = window.skillet || {}
is that it permits multiple scripts to safely add to the same namespace when they don't know in advance in what order they will execute. This can be helpful either if you want to be able to reorder your script inclusions arbitrarily without breaking your code, or if you want to load scripts asynchronously with the async attribute and so have no guarantee about execution order. See stackoverflow.com/questions/6439579/… -
Jack almost 10 yearsWhat advantage would this have over
var your_namespace = {};
? -
Alex Pacurar almost 10 yearsyou would have the possibility to extend the your_namespace object in different js files. When using var your_namespace = {} you cannot do that, as the object will be overridden by each file
-
Mirko almost 10 yearsShould you not check for
MYNS.subns = MYNS.subns || {}
?? -
Brett Ryan almost 10 yearsA good point that should be the exercise to the developers intent. You need to consider what to do when it does exist, replace it, error, use existing or version check and conditionally replace. I've had differing situations that call for each variants. In most cases you possibly have this as a low risk edge case and replacing can be beneficial, consider a rogue module that tried to hijack the NS.
-
Anthony Mason almost 10 yearsI was going to add an example as well; I commend you on this example code. @MarkAmery, I have to say that your comment is probably one of the most misunderstood components of javascript structures and you have provided an excellent explanation showing the scope of each function/variable and how to invoke them.
-
Soferio over 9 yearsThere is an explanation of this approach in the Book "Speaking Javascript" at page 412 if anyone has it, under the heading "Quick and Dirty Modules".
-
Brett Ryan over 9 yearsWill have to check it out. Was it talking negative due to the "dirty" in the heading? lol
-
James M. Lay over 8 yearsIt's worth wrapping
yourNamespace
in a lexical closure. -
Braden Best over 8 yearsOptimization tip: while
var foo = function
andfunction foo
are similar, being private; due to JavaScript's dynamically-typed nature, the latter is slightly faster as it skips a few instructions in most interpreters' pipelines. Withvar foo
, the type system has to get invoked to find out what type is being assigned to said var, while withfunction foo
, the type system automatically knows it's a function, so a couple function calls get skipped, which translates to fewer invocations of CPU instructions likejmp
,pushq
,popq
, etc, which translates to a shorter CPU pipeline. -
Braden Best over 8 yearsAlso, I would argue that
function foo
is more readable thanvar foo = function
, because even though thevar
syntax allows for vertical alignment, thefunction
syntax is explicit, and immediately clear to a human reading the code. Thevar
syntax leads to slightly longer mental parsing. So in a way, thefunction
syntax optimizes for both CPU and brain pipelines. Neato! This is just a matter of taste, but the way I would have done that last snippet is like this: pastebin.com/Zkk49aj9. It's subtle, but I find it faster to read. -
Brett Ryan over 8 years@B1KMusic that's both incorrect and poor advice. There's a distinct difference between the two. Using an assignment declares the function at runtime which allows delayed AND conditional function declarations, using
function myFunc
is defined at script evaluation and thus can not be declared conditionally. If you can any way prove your claims at efficiency then please provide it, you may find the opposite is true. For something defined only once it's not something you should be trying to optimise anyway. -
Braden Best over 8 years@brett oops. You're right. I was thinking of a different scripting language. Though I still insist the
function foo
syntax is more readable. And I still like my version. -
Stijn de Witt over 8 years@peter-mortensen Were these edits to my answer from '11 really necessary? It's definitely not vandalism what you are doing, don't get me wrong, but they are very superficial. I would prefer to remain the sole author of posts like these unless you really add something good.
-
Stijn de Witt over 8 yearsThere is one more big downside (imho) with doing
namespace.func = function(){ /* ... */};
: All these functions end up being anonymous. It is an inconvenience when debugging, looking at stacktraces etc. Please consider to stop writing anonymous functions. (I am the author of that blog post). -
jropella over 8 yearsThis is the defacto "standard" way that commercial web development houses do this (from my experience). It's the clearest, most concise, most readable way of achieving the "namespace" paradigm within javascript as far as I'm concerned.
-
DVK almost 8 yearsI've found this to be a very useful method for organizing client script into multiple files in large applications where functionality needs to be modular.
-
olimart almost 8 yearsHi, how do you call public functions from your snippet? I've tried
namespace.a();
-
nomæd almost 8 years@olivier yes, that's the idea. Although now with ES6, I usually use the shorthand syntax of object literals (ponyfoo.com/articles/es6-object-literal-features-in-depth)
-
Ciro Santilli OurBigBook.com over 7 yearsQuestion asking specifically for multiple files: stackoverflow.com/questions/5150124/…
-
daveruinseverything about 7 yearsThe answer provided in this example has a bug - I can't find a solution for this. In the original implementation of
skillet
, a private variableisHot
is declared. Subsequently,skillet
is extended to add thetoString()
method, and in this extension the private variabletoHot
is referenced. In my tests, this is not possible, as the private variable from the original implementation can't be referenced in a subsequent extension. Paste the code from this answer into the JS console in your browser.skillet.toString()
fails: ReferenceError: Can't find variable: isHot -
aamarks about 6 years@daveruinseverything The full example on the site referenced in the answer shows that causes an error. The benefit is you can create a second closure? to extend the namespace but the closures still can't access the private variables of the other, but that also means you don't have to worry about your private variables conflicting with those in the other. (I'm just starting to understand this, so may have some of that wrong.)
-
aamarks about 6 yearsAnd yet the MDN discourages the use of
with
? -
snoob dogg almost 5 yearsall your links seems dead
-
Wadih M. about 3 years@user406905 The big reason of namespaces is to minimize the chance of name collisions in the future within the global namespace that all code share. The key is to pollute the global namespace the least possible with local/custom variables, to avoid name collisions in the future, which are hard to troubleshoot and quickly becomes a mess. So the tradeoff is all your local variables will reside in that one namespace. And try to give it a name that hopefully another component will not use one day. That's what this best practice is about.
-
Andres about 3 yearsI just want to make emphasis on the set of
()
at the end of the function definition. They are required and it's easy to miss them. I had the same issue as @olimart and solved it by adding them. -
onefootswill about 2 yearsThis is great, but I have a question about
let
andconst
. Once you have created a namespacenamespace("com.ziesemer.myApp")
, is it possible to designate a property/object asconst
orlet
? Likecom.ziesemer.myApp.logger
- it seems to me that this can never be declared asconst
. I think with this I can't adopt some of those newer language features. Note: adopting the new Javascript modules is not an option unfortunately. -
ziesemer about 2 years@onefootswill - What you're looking for is not applicable here, as you're not strictly declaring variables - but new properties on to existing objects.
-
onefootswill about 2 yearsyep. I realise that. The question was put to me by our architect, who is fighting me on the inclusion of this approach. He seems content with polluting the global namespace in the creaky, old, low quality code-base. Some people ¯_(ツ)_/¯