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 :
1. I put the “var myClass =” there to prove that the new method returns the created class like the old method does, even if you use a namespace. That’s why I added “// myClass === davidwalsh.ui.Slider!” as a code comment.
2. That code lives at the following link, which is right at the top of the post: http://davidwalsh.name/mootools-namespace
3. Creating nested objects is tedious. And what if you want to override a class if it’s there, create it if it’s not? You’d use a bunch of if statements to create the nesting. This is far more efficient.
Nice, clever little tutorial. I had been “unconsciously” using the same as Alexander’s #3 solution of simply having nested objects for the sake of namespacing classes… and as you say, it’s cumbersome and doesn’t feel like a very efficient way of doing things while you code.
Will be using this technique from now on! Thanks.
Nice, clever little tutorial. I had been unconsciously using the same as Alexander’s #3 solution of simply having nested objects for the sake of namespacing classes… and as you say, it’s cumbersome and doesn’t feel like a very efficient way of doing things while you code.
Will be using this technique from now on! Thanks.
I found this to be very useful when working on an e-commerce site. I’ve organized it as sitename.classes.Checkout or sitename.classes.Default. Where sitename.classes.Checkout contains the class for checkout code and sitename.classes.Default is site-wide functionality.
My question is, any suggestion on how to organize the instances of the above classes when they are created?
For example (assuming this lives inside of a domready event):
//no namespace, just floating out there
myclass = new sitename.classes.Checkout({});
var myclass = new sitename.classes.Checkout({});
//namespaced
sitename.fn.Checkout = new sitename.classes.Checkout({});
//or, just forget about it and do
new sitename.classes.Checkout({});
Side note, I’m using Class a bit incorrectly here. I could just create an object to be a bit leaner, since it’s unlikely that I’ll be re-using much of this code.
Hi great blog! Did not come to an idea of “monkey patching” until I found this article. I sort of needed method overload feature in MooTools system as I was porting Java library to MooTools and below is what I have achieved so far. It is a derived version of the famous method overload done by John Resig.
Since you seem to know the internals of MooTools very well, I was wondering and appreciate very much if you can help me correct or give an advise how it is done in the code below will not produce any side effects. I wanted to protect the “overload” method to be called once it is “finalized” so I had to work on the “wrapper” function.
My limited insight into this is there should be 4 nests never more than one deep.. shared.basetemplate class.localtemplate class.protectedtemplate class.privatetemplate.. then when you declare and construct/create an object it builds it’s set of properties and functions from all the templates with that class name and from the shared template.. I am not sure how mooTools does it but I would use an array with classnames as key and directly find the definition of each quickly and I lean more to dynamically adding functions to applications and sharing data / classes / functions between them without accidentally calling a function from a different app… so it is likely an app creates it’s objects if they don’t exist in the correct namespace. Not sure how MooTools works, and this may not make sense, but I am working on a configuration that allows apps to work independently in the browser but still share classes, dataobjects and standard server request functions, while maintaining independent functionality. but I do things different, my application would maintain keyed arrays of objects under the appname.object so finding the object should be quick, most of it’s work happens at init time when libraries are checked and loaded and it’s private libs loaded the libs would be the classes it needs as some would be shared classes and other classes would be loaded under its own name, while yet some would be system classes and I find unlikely to check other classes unless user defined classes become available where they are entered by the user during the session, I however don’t find an app would dependent on anything 3rd party but could use as plugin or extra functionality if existed… just thinking