PrivateJavascript
From APIDesign
Can you hide anything in a dynamic language like Javascript? If there are no access modifiers to make something private and when everyone is allowed to dynamically add new fields, functions to any object or even remove them, then it is really hard to keep something private.
Still, as a framework writer you want to separate an API from an implementation. You need to make it hard (if not impossible) for your users to cheat and bypass your API. Documenting what is public and what is not is not enough. Users resort to documentation only when completely lost. Until then they act cluelessly and try to make things work first and only later (if ever) think of what they did. The users need to face a wall when they try to use an implementation detail (unless you want to get stuck as me with one mediawiki version). Can that be done in Javascript?
Scope instead of private
The private modifier is missing in Javascript. No fields can be guarded against modification. Where can one hide own state? Inside a method body! Looks like there is no way to inspect a body of a function and as functions can be nested (and see the other functions local variables) one can use following trick:
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> function create(what,counter) { var impl = { }; impl.what = what; impl.cnt = 0; impl.counter = counter; var api = { }; api.toggle = function() { if (impl.cnt++ % 2 == 0) { $(impl.what).hide("slow"); } else { $(impl.what).show("fast"); } $(impl.counter).text(impl.cnt); }; return api; } $(document).ready(function(){ var api = create($("a"), $("#counter")); $("a").click(function(event){ api.toggle(); event.preventDefault(); api.toggle(); }); }); </script> </head> <body> <a href="http://apidesign.org/">Toggle on and off</a><br>Toggle count: <span id="counter">0</span> </body> </html>
The API consist of one factory method (create) which returns an object with toggle method (there could be more method of course). This object keeps its internal state (reference to two document elements and a counter) in separate impl object which cannot be referenced by users holding just the API object. Looks like we successfully replaced missing access modifiers with a visibility scope.
Contest
I know all tricks a Java API users can do, but I do not claim to be a Javascript expert. Maybe there is a way to get on hand of the internals. Thus, let's try a contest: Who ever manages to write a Javascript code to:
var api = create($("a"),$("#counter"); api.toggle(); // TBD: somehow clean the internal counter api.toggle(); // now the internal counter shall be 1 and not 2
will be a winner and gets a special section in another API Design Tips podcast.
<comments/>