The following are a few tips and tricks that are gleaned from libraries in order to help you get started.
Namespacing and anonymous, self-executing functions
Although the technique for accessing methods and properties available in each library namespace can differ drastically, the concepts are similar. Most notably is the use of anonymous, self-invoking (or self-executing) functions. Take a look at the simplest example of namespacing below.
This namespace is effortless to implement, is the easiest to understand, and does not use a self-executing function. It is often referred to as object literal notation, or a nested object literal. If you never roll out your own library to other developers, and have no need for private methods and properties, then this is probably the most straightforward approach. The next example is a little more complicated.
Instead of using an object literal for the global namespace, I am using a self-executing function, and then storing (or pointing to) this object with the variable named
JSANT. This approach allows you the additional benefit of private methods and properties, which are only accessible from your public methods and properties. This is often referred to as the Modular Design Pattern.
The pattern is possible due to the fact that a function that self-executes, only executes once. Whatever is returned that one time, is now stored as a part of the namespace through your global variable. If you have also tried to master closures, well, this is your chance to shine. When an inner function like
JSANT.ajax.someMethod() accesses a variable within the outer JSANT function (like
myPrivateProperty) after it executes, then you have a closure.
If I were to walk through the previous code verbally, it would sound something like this:
- Create a self-executing anonymous function that contains all of your code, and protects your library from conflicting with variables already defined in the document.
- Create a variable called JSANT, point it to a function, and assign this to the window object.
- Pass JSANT one parameter, which will end up being the syntax for your selector.
- If an instance of the JSANT object already exists, then initialize it.
- If an instance of the JSANT object does not exist, then create it recursively.
- If the dollar selector is not being used by another library (making it undefined), assign it to the window object, and then point it to the JSANT object. The $ and JSANT can now be used interchangeably.
- Define the prototype of JSANT, and all additional namespaces, methods and properties.
As best as I understand it, and have read it explained elsewhere, JSANT must be declared with prototype. This is because the
instanceof follows the prototype chain to see if your object inherits from the prototype of the constructor function that is the class you are asking instanceof. If someone from the jQuery team would like to venture a better explanation in layman’s terms, it might be more helpful.
Constructor type checking
Variable arguments, function overloading, and the callback function
A function can gain access to the arguments that were passed into it using the arguments keyword. You do not even need to define variable names to match up with the arguments, as in the first example below. However, arguments is not an array, so in order to treat it as such, you will need to call (or convert) it into a real Array object.
If you are the only developer using the function, and know this list of variable arguments will serve a single purpose, then you can reap the benefits. However, if you want to provide more flexibility, and roll the function out as a utility to other developers, then you will probably need to consider the second example.
This approach might at first glance appear less flexible, but it allows you to treat your function as if it were being overloaded. Each conditional block can share local variables and perform a different task depending on the number of arguments. This also sets some expectations for other developers.
One topic that I did not cover in this tutorial is chainability — also known as object chaining, or DOM element chaining. This is a very powerful feature in many libraries that deserves special attention. Object chaining allows you to perform an action on an element in the DOM, return it as an object, and then perform another action on that object without having to specify the element again. You could call this a preview of things to come!