How do I declare a namespace in JavaScript?

607,610

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 value undefined. 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 variable undefined is writable, so anyone could rewrite its value. The third argument (when not passed a value) creates a variable named undefined which is scoped to the namespace/function. Because no value was passed when you created the name space, it defaults to the value undefined.

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.

Share:
607,610
Scott McKenzie
Author by

Scott McKenzie

iOS developer

Updated on January 13, 2022

Comments

  • Scott McKenzie
    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
      annakata about 15 years
      I 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
      Admin almost 14 years
      Take 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
      Matt about 12 years
      see also stackoverflow.com/questions/2102591/… for performance issues
    • Matt
      Matt about 12 years
      see also stackoverflow.com/questions/4125479/… for object vs function namespaces
    • Justin
      Justin almost 11 years
      This 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
      Sebastian Simon almost 3 years
      Meh, nowadays we have symbols and modules, so duplicate namespaces shouldn’t even be an issue.
  • annakata
    annakata about 15 years
    It's kind of blindsided me that anyone wouldn't love OLN. I just... what's not to love? What's so rigid?
  • annakata
    annakata about 15 years
    The important point is to be religious about expanding no further than the one root variable. Everything must flow from this.
  • user5880801
    user5880801 about 15 years
    1. 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
    Hungry Beast about 14 years
    The 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
    mckoss almost 14 years
    I'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
    Titi Wangsa bin Damhore over 13 years
    this style is compatible with my javascript editor (eclipse), as in, it can do auto formatting and indentation.
  • Lawrence Barsanti
    Lawrence Barsanti over 13 years
    I like this approach because it allows for private functions, variables, and pseudo-constants (i.e. var API_KEY = 12345;).
  • John
    John over 13 years
    Great 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
    mjallday over 13 years
    this gives me an error in IE7. var your_namespace = (typeof your_namespace == "undefined" || !your_namespace ) ? {} : your_namespace ; works better.
  • Lucent
    Lucent over 13 years
    I 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
    Carles Barrobés over 13 years
    I 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
    yoosiba over 13 years
    I 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
    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
    Palo over 13 years
    it should be var your_namespace = your_namespace = your_namespace || {} Works in every browser ;)
  • mckoss
    mckoss over 13 years
    This 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
    Omu over 13 years
    anybody knows why jQuery is not using this approach but the comma separated ?
  • user5880801
    user5880801 over 13 years
    This pattern works for singleton objects, but jQuery is a constructor function. In my example you can't call ns(), and jQuery needs this.
  • user406905
    user406905 about 13 years
    annakata: "The important point is to be religious about expanding no further than the one root variable."- Why is this?
  • Adi Roiban
    Adi Roiban about 13 years
    Now if JSLint would not complain about this legit structure everything will be so much better :)
  • paul
    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
    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
    paul almost 13 years
    @Anthony its just an suggestion and following the conventions. Moreover, its all about your personal preference.
  • John Kraft
    John Kraft almost 13 years
    JS Newbie here... why is it that I don't have to type ns().publicFunction(), that is... ns.publicFunction() works.
  • user5880801
    user5880801 almost 13 years
    @John Kraft, it's necause of the new keyword in front of the function 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 using new. As such, the final value that gets stored inside ns is an (unique) instance of that anonymous constructor. Hope it makes sense.
  • Darren Lewis
    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
    BumbleB2na almost 13 years
    kind 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
    SamStephens almost 13 years
    As 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
    Jared Beck over 12 years
    From 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
    user3167101 over 12 years
    @user406905: Because then you'd have two global identifiers, everything should live under the one namespace.
  • Antoine
    Antoine over 12 years
    Excellent. 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
    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
    Ryan over 12 years
    @Antoine - Why would it fail? jQuery should be the dependency and should be loaded preceeding your script
  • Antoine
    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
    Ryan about 12 years
    @alex - why should there be a shallow object structure?
  • user3167101
    user3167101 about 12 years
    @Ryan I meant that everything should be under MyApp, e.g. MyApp.Views.Profile = {} rather than MyApp.users = {} and MyViews.Profile = {}. Not necessarily that there should only be two levels depth.
  • Flash
    Flash almost 12 years
    Also worth mentioning that in the above examples this refers to what you would expect in publicFunction, but refers to the global object in internalFunction. I usually add var self = this at the top to avoid confusion.
  • Gustavo Gondim
    Gustavo Gondim over 11 years
    This is called today IIFE (Immediately Invoked Function Expression). Thanks for your answer +1!
  • Gustavo Gondim
    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
    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
    mrówa about 11 years
    @CpILL: not sure if still relevant, but the third, undefined argument is source of the variable of value undefined. While working with older browsers / javascript standard (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variable undefined is writable, so anyone could rewrite its value. Adding third, additional argument you are not passing makes it value undefined, so you were creating namespace-scope undefined which won't be rewritten by outside sources.
  • Sriram
    Sriram about 11 years
    @Palo Can you please explain why it should be like this? var your_namespace = your_namespace = your_namespace || {}
  • SapphireSun
    SapphireSun almost 11 years
    So 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
    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
    Laoujin almost 11 years
    If 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
    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 be var n = n && n.name === "NSNAME" ? n : { name: "NSNAME"};
  • Mark Amery
    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
    Jack almost 10 years
    What advantage would this have over var your_namespace = {};?
  • Alex Pacurar
    Alex Pacurar almost 10 years
    you 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
    Mirko almost 10 years
    Should you not check for MYNS.subns = MYNS.subns || {} ??
  • Brett Ryan
    Brett Ryan almost 10 years
    A 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
    Anthony Mason almost 10 years
    I 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
    Soferio over 9 years
    There 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
    Brett Ryan over 9 years
    Will have to check it out. Was it talking negative due to the "dirty" in the heading? lol
  • James M. Lay
    James M. Lay over 8 years
    It's worth wrapping yourNamespace in a lexical closure.
  • Braden Best
    Braden Best over 8 years
    Optimization tip: while var foo = function and function 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. With var foo, the type system has to get invoked to find out what type is being assigned to said var, while with function 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 like jmp, pushq, popq, etc, which translates to a shorter CPU pipeline.
  • Braden Best
    Braden Best over 8 years
    Also, I would argue that function foo is more readable than var foo = function, because even though the var syntax allows for vertical alignment, the function syntax is explicit, and immediately clear to a human reading the code. The var syntax leads to slightly longer mental parsing. So in a way, the function 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
    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
    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
    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
    Stijn de Witt over 8 years
    There 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
    jropella over 8 years
    This 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
    DVK almost 8 years
    I'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
    olimart almost 8 years
    Hi, how do you call public functions from your snippet? I've tried namespace.a();
  • nomæd
    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
    Ciro Santilli OurBigBook.com over 7 years
    Question asking specifically for multiple files: stackoverflow.com/questions/5150124/…
  • daveruinseverything
    daveruinseverything about 7 years
    The answer provided in this example has a bug - I can't find a solution for this. In the original implementation of skillet, a private variable isHot is declared. Subsequently, skillet is extended to add the toString() method, and in this extension the private variable toHot 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
    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
    aamarks about 6 years
    And yet the MDN discourages the use of with?
  • snoob dogg
    snoob dogg almost 5 years
    all your links seems dead
  • Wadih M.
    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
    Andres about 3 years
    I 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
    onefootswill about 2 years
    This is great, but I have a question about let and const. Once you have created a namespace namespace("com.ziesemer.myApp"), is it possible to designate a property/object as const or let? Like com.ziesemer.myApp.logger - it seems to me that this can never be declared as const. 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
    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
    onefootswill about 2 years
    yep. 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 ¯_(ツ)_/¯