Introduction
I started to seriously consider javascript as a development language three years ago when I tried to implement a card game simulator (the pokemon one). You will find some running code here: PokeMul. The project is not really finished nor over but a Flash version of the game has been officially released and it outblooms my own realisation (Pokemon TCG).This is why I decided to focus on putting in common tools and technics that could be reused in other projects.I have been impressed by jQuery which offers a rich, comprehensive and widely accepted API and my goal is to achieve the same kind of success (let be optimistic). More seriously, I already learned a lot by doing this, I hope this would be helpful to someone.
Before going any further, I make the assumption that you are familiar with the javascript language and some of its "advanced" concepts (objects, prototype, closure...).
If not, I highly advise you to go to this well documented learning site: Codeacademy.
Most of the libraries you would find on the net are delivered into a single javascript file (for instance: jquery.js). Once loaded and evaluated in your HTML page, it extends the execution context with its own API.
Very often, those libraries own a hidden part that contains the implementation details. For instance, some variables are kept as caches to store information. The same way, some methods - known only by the library developpers - are used to put in common some code.
My research is to know how I can control what is exposed or not.
Demonstration
I created a page to demonstrate the different ways to declare things and how they appear in the global context: demonstration. Don't hesitate to use "view source" on the page to see how it is coded.How does it work?
The starting point is to enumerate all the members of the global context to check what becomes available to the user of a library.
As this enumeration is done several times, everything is stored in an object (used like a dictionary). It allows me to see what is different between two consecutive calls.
// Maintain the known properties inside a global map
var members = {
_count: 0
};
// The following are "known" because declared below (they are not 'counted')
members[ "members" ] = 0;
members[ "echo" ] = 0;
members[ "enumMembers" ] = 0;
members[ "addInclude" ] = 0;
The enumeration function itself uses the for ... in syntax to enumerate members. By default, this is used to enumerate the global object.You will also notice the use of an addInclude function that is capable of dynamically inserting a script tag and wait for the loading to be done (based on the jQuery implementation). This will be detailled later.
What does it demonstrate?
In the first example, you see that the global variable isItPrivate1 appears before its has been declared. This is inherant to javascript which declares the function and variables before executing the code.On the contrary, by dividing the script tag in two parts, the second example shows that you can control when the variable will be declared: isItPrivate2 appears only on the third enumeration.
In any case, both examples are not relevant because they don't demonstrate the use of a separate javascript file.
I created the third example to show that if you declare variables in an external javascript file, it is merged with the current context once the script is loaded. It means that if the library needs to use global variables the developper has to control their visibility: it has to be done differently.
I wanted to see how jQuery extends the context, so I loaded it. As a result, only two new members are inserted in the global context: $ (the famous jQuery shortcut) and jQuery.
On the other hand, enumerating the jQuery object content shows lots of members that are not necessarily the ones documented.
Finally, by creating a closure, the last example demonstrates how an object can be declared to expose a function that uses a variable that is not in the current context:
(function(){
var isItPrivate4 = "Yes!";
this[ "example4" ] = {
isItPublic4: function(){
return isItPrivate4;
}
};
})();
This will be the preferred solution to develop the library.