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?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
sjmartin
  • 3,912
  • 4
  • 19
  • 32
  • 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: `|| {};`. – chRyNaN Apr 30 '15 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? – sjmartin Apr 30 '15 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. – Etheryte Apr 30 '15 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. – chRyNaN Apr 30 '15 at 16:37
  • Thank you both @chRyNaN and @nit! I guess I will need to try this myself as I couldn't find anything online to answer what specifically happens. – sjmartin Apr 30 '15 at 16:42
  • 1
    This is why require.js exists: to avoid polluting the global namespace and manage clashes in a reasonably sane manner. – McCroskey Apr 30 '15 at 16:47
  • Or avoid global scope and define your code in an [IIFE](http://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript?rq=1) – Jasen Apr 30 '15 at 16:59

2 Answers2

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.

Community
  • 1
  • 1
devconcept
  • 3,665
  • 1
  • 26
  • 40
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

Paul S.
  • 64,864
  • 9
  • 122
  • 138