Create Namespaced Classes with MooTools
MooTools has always gotten a bit of grief for not inherently using and standardizing namespaced-based JavaScript classes like the Dojo Toolkit does. Many developers create their classes as globals which is generally frowned up. I mostly disagree with that stance, but each to their own. In any event, namespaces are technically just nested objects and I recently shared with you how to create and retrieve nested objects with MooTools. With those utility functions available, I've modified Class so that you can create namespaced classes easily!
The MooTools JavaScript
The technique below is very much like monkey patching:
(function() { // Keep reference to the original Class var klass = Class; // Redefine class ("that's deep") Class = function(name, params, context) { // Find out if this is namespaced or the original method var namespaced = (arguments.length > 1); // Add the class name to the param list if(namespaced) params.$name = name; // Create and get the original class var original = new klass(namespaced ? params : name); // If namespaced, set class into namespace if(namespaced) Object.place(name, original, context); // Return this newly created class! return original; }; })();
I keep a reference to the original Class
, as I'll be using it within my new Class
function. The new signature allows for a namespaced class name, the usual class properties, and the context which may be passed to the Object.place method. The first step is analyzing the arguments provided to Class; if one argument, it's a traditional class; if more than one argument is provided, we know we're trying to create a namespaced class and will act accordingly. You'll also notice that I add a $name
property to the class prototype, providing the given class name to the class for later use. I've found the class' declaredClass property incredibly helpful within Dojo.
Here's how you'd use the new Class function:
// Create a namespaced class var myClass = new Class("davidwalsh.ui.Slider", { initialize: function() { // Do stuff! }, doSomething: function(){} }); // myClass === davidwalsh.ui.Slider! // Create an instance of the class var myInstance = new davidwalsh.ui.Slider({ // props }); // Get the name of the declared class var instanceClassName = myInstance.$name; // equals "davidwalsh.ui.Slider"
The first argument becomes the namespace and class name as a string. The second argument is the traditional parameters argument. If only one argument is provided to the Class function, the class is created and returned per usual; in fact, both the namespaced method and traditional method return the newly created class. The method provided above is completely backward compatible so you wont have rewrite your existing code.
Namespaced classes are probably a good idea, as many would argue that "polluting" the global namespace with numerous objects can lead to problems. In any event, this namespacing method should help you make the most of my set/get nested object methods and allow you to keep the global namespace as clean as you'd like!
Interesting article !
I’m not a namespacing expert, so here goes nothing :
The big advantage of such a style of class naming is that instead of having a global variable holding each class, the globale namespace is instead polluted with the topmost level of each namespaces used (assuming we have some from core, some from more, some from a few other third party sources and so on…). Plus we add the overhead to lookup properties of properties (it has been proven that it takes more time to access object.child1.child2 than just object). So as I understand it, it gives the clearer categorization of classes (which is the idea behind Request.HTML, Request.JSON already) and reducing a bit the amount of polution of the global namespace, right ?
Sorry to spam the post, but I thought about all this again and wonder about something else.
1) the variable
var myClass
in your example will be in the global namespace, so how using namespacing will reduce pollution ?2) Where is
Object.place
defined ? it’s not in the Core or More documentation, nor in JS itself ?3) How is using this monkey patching snippet you posted different from doing :