I want to be able to package my JavaScript code into a 'namespace' to prevent name clashes with other libraries. Since the declaration of a namespace should be a simple piece of code I don't want to depend on any external libraries to provide me with this functionality. I've found various pieces of advice on how to do this simply but none seem to be free of errors when run through JSLint (using 'The Good Parts' options).
As an example, I tried this from Advanced JavaScript (section Namespaces without YUI):
"use strict"; if (typeof(MyNamespace) === 'undefined') { MyNamespace = {}; }
Running this through JSLint gives the following errors:
Problem at line 2 character 12: 'MyNamespace' is not defined. Problem at line 3 character 5: 'MyNamespace' is not defined. Implied global: MyNamespace 2,3
The 'Implied global' error can be fixed by explicitly declaring MyNamespace
...
"use strict"; if (typeof(MyNamespace) === 'undefined') { var MyNamespace = {}; }
...and the other two errors can be fixed by declaring the variable outside the if block.
"use strict"; var MyNamespace; if (typeof(MyNamespace) === 'undefined') { MyNamespace = {}; }
So that works, but it seems to me that (since MyNamespace
will always be undefined at the point it is checked?) it is equivalent to the much simpler:
"use strict"; var MyNamespace = {};
JSLint is content with this but I'm concerned that I've simplified the code to such an extent that it will no longer function correctly as a namespace. Is this final formulation sensible?
JavaScript does not provide namespace by default. However, we can replicate this functionality by making a global object which can contain all functions and variables.
The global namespace is the top space of Javascript that contains the variables. In a browser, it's known as the window.
Namespace is a context for identifiers, a logical grouping of names used in a program. Within the same context and same scope, an identifier must uniquely identify an entity. In an operating system a directory is a namespace.
Don't take JSLint's word as gospel. Much of what it says is sensible, but it also comes with a lot of Crockford's personal dogma attached. In particular I don't always agree with him about the best place for var
.
"use strict"; if (typeof(MyNamespace) === 'undefined') { MyNamespace = {}; }
That one's no good; JSLint is correct to complain about the implied global. 'use strict'
requires you don't imply globals.
"use strict"; if (typeof(MyNamespace) === 'undefined') { var MyNamespace = {}; }
That's fine. The var
is hoisted so MyNamespace
is present and set to undefined
on entering the code block. So you could do that test as (MyNamespace===undefined)
even without the typeof
operator's magic ability to let you refer to variables that don't exist.
The other way is to use the unambiguous in
operator (which is the only way to distinguish between an absent property one that is present but set to undefined
). For the case of globals in a normal browser script, you can use it against the global window
object:
'use strict'; if (!('MyNamespace' in window)) { window.MyNamespace = {}; }
(JSLint doesn't like that either, as ‘assume a browser’ doesn't seem to define window
for some unfathomable reason. Hey ho.)
You can try a much shorter version:
var MyNamespace = MyNamespace || {};
This should be valid in JSLint, even in strict mode, using the name if it already exists and creating it if it doesn't, as best a namespace in JavaScript can be expected to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With