2

I understand why namespaces are good - to prevent too many global definitions and to prevent code from being overwritten, but i'm trying to dig a bit further into the following syntax:

// not safe, if there's another object with this name we will overwrite it
var MYAPPLICATION = {};

// We need to do a check before we create the namespace
if (typeof MYAPPLICATION === "undefined") {
    var MYAPPLICATION = {};
}

// or a shorter version
var MAYAPPLICATION = MYAPPLICATION || {};

Ok, the first line of code isn't safe because MYAPPLICATION could be defined somewhere else or by a different library.

The second line checks to see if it exists and if it doesn't go ahead and define the var MYAPPLICATION with a new object.

My question is, what happens when MYAPPLICATION is defined beforehand? The code won't initialize the variable and the namespace isn't created? Does that mean your code would just never work? If so, what then?

7
  • 1
    If the MYAPPLICATION variable is already initiated it will use the already initiated variable: MYAPPLICATION = MYAPPLICATION. If it is not initiated it will create a new object: || {};. Commented Apr 30, 2015 at 16:33
  • So if it uses the pre existing one that was created by someone else, isn't there a possibility that your code will clash? If someone else defined a function foo(){return "bar"} and my code defined the same function foo(){return "hello world"} what happens when function foo() is called? Commented Apr 30, 2015 at 16:35
  • 1
    @sjmartin Yes, there is a chance things will clash. That's why you should go with a namespace that's reasonably unique and not worry about it that much. Commented Apr 30, 2015 at 16:37
  • 1
    You will probably get a TypeError in that scenario. Your namespace should be unique. All your functions and objects should belong to that one namespace. This limits the possibility of a clash with other libraries. Commented Apr 30, 2015 at 16:37
  • 1
    This is why require.js exists: to avoid polluting the global namespace and manage clashes in a reasonably sane manner. Commented Apr 30, 2015 at 16:47

2 Answers 2

3

What will happen is that your aplication will overwrite the properties of the previous one or viceversa depending on wich is executed first.

In javascript "almost" everything can be overwriten. Your aplication is just a simple object in global scope so if the other aplication is written like this.

var MYAPPLICATION = {};
MYAPPLICATION.foo = function () {....}

And yours is

var MYAPPLICATION = MYAPPLICATION || {};
MYAPPLICATION.bar = function () {...}

You will end up with a global variable called MYAPPLICATION with two properties 'foo' and 'bar' with functions defined on it.

One will be yours and the other is not so you can end up with unespected behaviour of your code. So in other words there is no really a safe way of create a namespace in javascript.

You can check this SO article Is there a "concise" way to do namespacing in JavaScript? for more information but I personally recommend you that you use the sandbox pattern instead. This will help you isolate your code a little better.

This is post contains an example to get you started. This adresses some problems of the namespace pattern like having multiple versions of the same app and long name resolution like app.module.foo.bar.daa.

Sign up to request clarification or add additional context in comments.

Comments

2

Your second example will not work quite as you expect; the var will be hoisted. ES5 is forgiving of trying to var the same identifier multiple times though (see spec §10.5, 8. c.)

In strict mode you could get a ReferenceError if you simply dropped the var

Instead, work off the global object, e.g. window

if (!window.my_namespace) {
    window.my_namespace = {};
}

or if you don't want to assume it will be truthy you could check the existence of a property

if (!(my_namespace in window)) {
    window.my_namespace = {};
}

You can further keep the namespace clean by writing IIFEs

if (!window.my_namespace) {
    window.my_namespace = (function () {
        var o = {}, a = 'foo', b = 'bar';
        o[a] = b;
        return o; // pass out reference
    }()); // {foo: "bar"}
}

Or consider if you even need the global namespace at all if you keep everything inside your IIFE

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.