In Javascript is extremely easy to write spaghetti code, when you write something like:
var foo = 12;
function log(value)
{
console.log(value);
}
both foo variable and log function become part of the global namespace, you can imagine what could happen when you add a new Javascript file that also includes a foo function.
In .NET to better organize the code we have Namespaces that can be used to group types together and prevent naming collision, while Javascript misses this concept natively it can be simulated through objects and that’s what Microsoft did inside WinJS Library.
Here’s how we can expose a ‘Logger’ object inside ‘MyLibrary’ namespace defined inside myLibrary.js file.
(function ()
{
//Define the namespace
var myLib = WinJS.Namespace.define("MyLibrary");
//Adds a logger object to the namespace
myLib.Logger = {
log: function (text) {
console.log(text);
}
}
})();
note that to also definition is self contained inside a self invoking function (very common patter in Javascript)
Using the Logger object is even simpler:
//Log
var logger = MyLibrary.Logger;
logger.log("log this");
//Or simply...
MyLibrary.Logger.log("loggin again");
namespaces can be aggregated so if you add a new file myUltraLibrary.js containing:
(function () {
var myLib = WinJS.Namespace.define("MyLibrary");
myLib.UltraLogger = {
log: function (text) {
console.log("ultra: " + text);
}
}
})();
you can now use the newly added UltraLogger object:
MyLibrary.Logger.log("loggin again");
MyLibrary.UltraLogger.log("Ultra logging");
Nice, but now I’m using sort of static classes exposed from a namespace, what if I want something like real .NET classes?
You’re probably aware that using some patterns you can simulate classes in in a classless language like Javascript but ,again, thanks WinJS we can quickly have classes in Javascript too, here’s how:
(function () {
var myLib = WinJS.Namespace.define("MyLibrary");
var multiLogger=WinJS.Class.define(function (loggerId) {
this._loggerId = loggerId;
this._textToLog = null;
},
{
tag: "multiLogger",
id: {
get: function () { return this._loggerId },
},
text: {
get: function () { return this.textToLog },
set: function (value) { this.textToLog = value; }
},
log: function () { console.log(this.textToLog) }
},
{
fastLog: function (text) { console.log(text) }
});
myLib.MultiLogger = multiLogger;
})();
the code add a new class MultiLogger to MyLibrary namespace using WinJS.Class.define method that accepts 3 parameters: a function representing class constructor (or null for an empty one) an object exposing instance properties (note that EcmaScript 5 allows definition of both get and set function associated to a property) and an optional object exposing static methods.
How can we use the MultiLogger class? exactly as if it was a .NET class:
//MultiLogger1
var multiLogger1 = new MyLibrary.MultiLogger(42);
// multiLogger1.id = 22; //We can't since id is read onlt...
var id = multiLogger1.id; //returns 42
multiLogger1.text = "Text to log";
multiLogger1.log();
//MultiLogger2
var multiLogger2 = new MyLibrary.MultiLogger(43);
multiLogger2.text = "more text...";
multiLogger2.log();
very nice isn’t it? :-)