Da die Menge an JavaScript in Webprojekten immer und immer mehr zunimmt, gilt es auch auf Clientseite für Ordnung zu sorgen, neben der Dateibasierten Organisation von JavaScript Files, kann man in JavaScript auch auf Namespaces zurückgreifen und somit die JavaScript API etwas ordnen.
Grundlegend sind Namespaces in JavaScript nichts anderes, als eine Verkettung von Objekten. In der einfachsten Form kann man in JavaScript demnach Namespaces wiefolgt definieren
// create root namespace
var DotNetRocks = new Object();
// create subnamespaces
DotNetRocks.Client = new Object();
DotNetRocks.Client.Models = new Object();
// create a class within the namespace
DotNetRocks.Client.Models.User = function(firstName, lastName){
this.FirstName = firstName;
this.LastName = lastName;
this.greet = function(){
alert("Hello " + this.FirstName + " " + this.LastName);
};
};
// create a new instance
var currentUser = new DotNetRocks.Client.Models.User("Thorsten", "Hans");
// calling the instance method
currentUser.greet();
Wie man sieht ist es sehr einfach Namespaces in Javascript zu erstellen und die einzelnen Klassen darin anzusiedeln. Allerdings bringt dieser Lösungsweg einige Probleme mit, welche man im täglichen Leben natürlich nicht haben möchte.
Das Snippet müsste erweitert werden, so dass Root- und SubNamespaces nur erstellt werden wenn diese noch nicht existieren, weil sonst die jeweiligen Objektdefinitionen überschrieben würden.
Anstatt dessen, sollte man sich eine einfache Hilfsklasse erstellen, die das Registrieren von Namespaces übernimmt. Auch Microsoft AJAX bringt eine solche Funktionalität mit sich. Um ein Verständnis für den Aufbau der Komponente zu erlangen, empfiehlt es sich allerdings einfach mal die paar Zeilen JavaScript zu lesen bzw. zu schreiben.
// ensure Namespace and Manager objects
if (typeof Namespace == 'undefined') var Namespace = {};
if (!Namespace.Manager) Namespace.Manager = {};
// create a JSON object
Namespace.Manager = {
// define register method
Register: function (namespace) {
// split the input on each dot to provide subnamespaces
namespace = namespace.split('.');
// ensure root namespace
if (!window[namespace[0]]) window[namespace[0]] = {};
// create all the subnamespaces, if not present
var strFullNamespace = namespace[0];
for (var i = 1; i < namespace.length; i++) {
strFullNamespace += "." + namespace
;
eval("if(!window." + strFullNamespace + ")window." + strFullNamespace + "={};");
}
}
};
Diese kleine Snippet muss logischer Weise innerhalb der Page bekannt gemacht werden.
Hierbei gibt es sowohl in ASP.NET, als auch in SharePoint diverse Wege wie man dies erreichen kann. Entweder man geht den klassischen Weg über eine MasterPage mit entsprechendem <script/> Tag, oder man schreibt ein kleines HttpModule welches das Script immer in die Response rendert. In SharePoint kann man allerdings noch die etwas elegantere Lösung wählen und ein DelegateControl erstellen und dieses, mit einer sehr niedrigen Sequence Number in den AdditionalPageHead einbinden.
Die Verwendung der Register Methode ist denkbar einfach:
Namespace.Manager.Register("DotNetRocks.Client.Models");
Auf die eigentliche Typdefinition wirkt sich die alternative Namespace-Definition allerdings nicht aus, mit der Namespace.Manager.Register Variante sieht die Typdefinition und –Verwendung wiefolgt aus
Namespace.Manager.Register("DotNetRocks.Client.Models");
DotNetRocks.Client.Models.User = function (firstName, lastName) {
this.FirstName = firstName;
this.LastName = lastName;
this.greet = function () {
alert("Hi " + this.FirstName + " " + this.LastName);
};
};
var myUser = new DotNetRocks.Client.Models.User('Thorsten', 'Hans');
myUser.greet();
Was bringen Namespace in JavaScript?
Javascript habe ich selbst lange Zeit als notwendiges Übel identifiziert, doch spätestens mit dem jQuery – Hype fing JavaScript an Spaß zu machen. Ich selbst setzte an immer mehr stellen auf Plain Javascript anstatt irgendwelche ASP.NET Controls von Drittanbietern zu verwenden. Aber Namespaces in JavaScript!? Braucht man das wirklich?
- Ja! Es hilft definitiv dabei den clientseitigen Code lesbarer und wartbarer zu machen. Klar bedarf es minimal mehr Zeit bei der Entwicklung, aber der unterschied ist so minimal – und beim Ersten Fehlersuchen eh schon wieder eingespart.
Wohin führt dies?
Doch wohin führen uns solche Konzepte in JavaScript, durch den Einsatz von Namespaces in JavaScript ist man schnell an dem Punkt wo man sagt “Dann machen wir pro Namespace einen Ordner um in der Solution schneller navigieren zu können. Na, wenn wir schon dabei sind, dann packen wir doch gerade mal jede JS-Klasse in eine eigene Datei, denn wenn schon Ordnung dann richtig.
Das klingt ja grundsätzlich nicht falsch, allerdings impliziert dies meiner Meinung nach auch den Einsatz von Libs wie HeadJS, damit man nicht hunderte von JS Files beim PageLoad laden muss.. und schon bläht sich die Sache immer und immer weiter auf. Daher gilt es abzuwägen ob und in welcher Form eine physikalische Strukturierung von JavaScript Sinn macht und Notwendig ist.
Was meint ihr?