Namespaces in JavaScript

It is difficult to work with independently developed JavaScripts. There is no built-in Java "package" (or C++ "namespace")-like feature in JavaScript. You have to use script objects for everything. Yes, there is a namespace proposal in JavaScript 2.0. But, what do we do now?

Well designed JavaScript APIs (like TrimPath API) avoid polluting global namespace by exposing API as methods in few (may be just one!) objects. But, most of the useful JavaScript code out there may not have been written in that style. There will be many global variables and functions. You may still find those scripts useful. It is not always feasible or desirable to edit such scripts to avoid global namespace pollution. How about a simple namespace solution for JavaScript (in the context of Mustang's JavaScript engine)?


function namespace(code) {
    // new global scope for the new namespace
    var myGlobals = new Packages.javax.script.SimpleBindings();

    // use 'engine' variable to execute code with
    // new global scope

    // 'engine' variable is of type javax.script.ScriptEngine    
    // This is exposed in jrunscript tool. But, it is easy to expose this
    // from your Java programs as well. Please refer below...
    engine.eval(code, myGlobals);

    // return a wrapper object that exposes
    // globals of the new namespace 

    return new JSAdapter() {
        __has__: function (name) {
            return myGlobals.containsKey(name);
        },
        __get__: function (name) {
            return myGlobals.get(name);
        },
        __getIds__ : function () {
            return myGlobals.keySet().toArray();
        }
    }
}

Exposing engine variable from Java code


      ScriptEngineManager m = new ScriptEngineManager();
      ScriptEngine engine = m.getEngineByName("js");
      // add a global variable called "engine"
      engine.put("engine", engine);

With the above definition of namespace (I'd have preferred 'package', but that is a JavaScript reserved word!), we can write:

var ns = namespace('var s = 3; function hello() { print('hello'); }');

// print 3 - value from namesapce
print(ns.s); 

// print 'hello' by calling hello in namespace ns
ns.hello();  

For better package/namespace level encapsulation, we may want to expose only functions from the namespace and hide all package-level variables. It is easy to modify above namespace function as shown below:


function namespace(code) {
    var myGlobals = new Packages.javax.script.SimpleBindings();
    engine.eval(code, myGlobals);

    return new JSAdapter() {
        __has__: function (name) {
            // do not expose non-function type stuff!
            var res = myGlobals.containsKey(name);
            if (res) {
                return typeof(myGlobals.get(name)) == 'function';
            }
        },
        __get__: function (name) {
            // do not expose non-function type stuff!
            var val = myGlobals.get(name);
            return typeof(val) == 'function'? val : undefined;
        },
        __getIds__ : function () {
            return myGlobals.keySet().toArray();           
        }
    }
}

Now, we have namespace. What about namespace using or package import-like feature? Well, that is a topic for another blog or an exercise to reader :-)

Comments:

can any one please send me the differnce between module level encapsulation and object level encapsulation .if possible please send them with code snippets.

Posted by bhupesh on May 05, 2007 at 02:27 PM IST #

Post a Comment:
Comments are closed for this entry.
About

sundararajan

Search

Archives
« May 2015
SunMonTueWedThuFriSat
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
      
Today
Bookmarks
Links

No bookmarks in folder

Blogroll

No bookmarks in folder

News

No bookmarks in folder