What is a Namespace
Namespace is a container for set of identifiers, functions, methods and all that. It gives a level of direction to its contents so that it will be well distinguished and organized.
Why is Namespace Needed
Namespace we must have known from any language or the other. What it does is, it doesn’t allow us to pollute our code base and makes it cleaner by grouping our code logically and avoiding unexpected and expected collision.
To achieve this, what we need to do is to create a namespace in application and use it.
In any modern day application, Namespace is a must to have because at the end, we need third party libraries and components.
Importance of Namespace in JavaScript
Unfortunately JavaScript doesn’t provide namespace by default. So anything (function
, method
, object
, variable
) we create in JavaScript is global
and we continue polluting that global namespace
by adding more to that.
But the good news is that we can create namespace in JavaScript and that too very easily.
As we know, in JavaScript everything is an object and creating an object is very simple. We can achieve namespace very easily with some minor tweaks.
Let's See How JavaScript Makes All Things Global
function calculateTax(item) {
return item.price * 1.40;
}
var product = function (cost) {
this.cost = cost;
this.getCost = function(){
return this.cost;
};
};
function doTaxCalculations() {
var p = new product(100);
alert(calculateTax(p.getCost()));
}
In the above code, the two functions and the class, all three are settled down in the global space.
It's a simple code base but it contains 3 global items (calculateTax
, product
, doTaxCalculations
).
These three will really put us in trouble if we are using 3rd party libraries and they also contain the same name.
Like if it is used before other library, it will be overridden by Library and vice versa.
JavaScript Sample Namespace
In JavaScript, it is nothing but a single global object which will contain all our functions, methods, variables and all that. Here ‘MYAPPLICATION
‘ is acted as a JavaScript namespace and the only global object
which contains all other items.
var MYAPPLICATION = {
calculateTax: function (item) {
return item * 1.40;
},
product: function (cost) {
this.cost = cost;
this.getCost = function(){
return this.cost;
};
},
doTaxCalculations: function () {
var p = new MYAPPLICATION.product(100);
alert(this.calculateTax(p.getCost()));
}
}
To access any of the methods or variables, you need to fetch it through the MYAPPLICATION
.
var newProduct = new MYAPPLICATION.product(200);
alert(p.getPrice());
Not only single namespace like the above one, but we can create nested JavaScript Namespace as well.
Let's look at a sample of nested JavaScript Namespace.
Nested JavaScript Namespace
It is nothing but a namespace inside a namespace, which provides better modularization for complex JavaScript application.
var MYNESTEDAPPLICATION = {
MODEL: {
product: function (price) {
this.price = price;
this.getCost = function(){
return this.price;
};
}
},
LOGIC: {
calculateTax: function (item) {
return item * 1.40;
},
doCalculations: function () {
var p = new MYNESTEDAPPLICATION.MODEL.product(100);
alert(this.calculateTax(p.getCost()));
}
}
}
Note
Do your naming convention in such a manner that it will be self explanatory and
not conflict other Library. May be I am not that good at those.
Create Namespace If It Does Not Exist
Like the above, we use a single global object, but it might conflict with other global.
To avoid this, we can check the existence before creating it and it is a good practice.
var MYSAMPLEAPP = {};
if (typeof MYSAMPLEAPP === "undefined") {
var MYSAMPLEAPP = {};
}
var MYSAMPLEAPP = MYSAMPLEAPP || {};
The above one is the safest way to create namespace, but what we can do is we can make it more easy by writing a function which will create our namespace.
Function To Create Namespace
We just need to call a simple function with some arguments to create our namespace. Then, we can define all functions and variables in that namespace.
var MYNAMESPACE = MYNAMESPACE || {};
var newNamespace = MYNAMESPACE.createNameSpace("MYNAMESPACE.COUNTRY.STATES");
newNamespace.product = function(price) {
this.price = price;
this.getCost = function(){
return this.price;
}
};
MYNAMESPACE.createNameSpace = function (namespace) {
var namespaceArr = namespace.split(".");
var parent = MYNAMESPACE;
if (namespaceArr[0] === "MYNAMESPACE") {
namespaceArr = namespaceArr.slice(1);
}
for (var i = 0; i < namespaceArr.length; i++) {
var partname = namespaceArr[i];
if (typeof parent[partname] === "undefined") {
parent[partname] = {};
}
parent = parent[partname];
}
return parent;
};
Basically, the createNameSpace
function splits the string
and creates a nested namespace from it.
<code>MYNAMESPACE.createNameSpace("MYNAMESPACE.COUNTRY.STATES");</code>
Output
var MYNAMESPACE = {
COUNTRY: {
STATES: {
}
}
}
Namespaces Aliasing
We can achieve this by simply aliasing the namespace in a local variable:
var state = MYNAMESPACE.COUNTRY.STATES;
Use state
instead of the whole namespace to fetch all the variables and functions.
Note
However, the above solution regarding namespace is perfectly valid and useful for most cases.
But there might be some cases where this isn’t the best choice to make.
Here, there is only single global instance but nothing stops us from accessing the inner variables directly.
Somehow, we need to control the access to the private
variables. This can be achieved by “Creating modular application using modules” that will encapsulate date.
Using Module
MYAPP.MODEL.PRODUCTS.product = function(cost) {
var cost = cost;
return {
isTaxable: true,
getCost: function(){
return cost;
}
};
};
cost
accessible to the function because of closure else it is not accessible directly.
isTaxable
and getCost
are public
ones.
There are many patterns to achieve this.
Like making everything private and exposing what we need to expose.
MYAPP.MODEL.PRODUCTS.product = function(cost){
var cost = cost;
var isTaxable = true;
var getCost: function(){
return cost;
};
return {
isTaxable: isTaxable,
getCost: getCost
};
};
Though there may be some security issues in the above written samples, we can make it more and more perfect.
We can prevent the access by reference to any variable inside the namespace. The are lot more patterns we can follow to achieve this.
Conclusion
The use of Namespace makes the JavaScript code modular and structured also easy to read, understand and modify. So without polluting the global namespace, we can achieve all these things, any way we have to use the global namespace but we are not messing things there.
Hope this helps. Thanks for reading.
CodeProject
