Blog Entry - 2nd December 2009 - Programming - JavaScript

"Nest" - A Crazy JavaScript Module Scheme


This blog entry is to support my comment at David Flanagan's blog entry on namespaces.

The following is a crazy module loading scheme that I have developed purely for fun.

I could call it "Closure" (as that is the essence of the scheme), but Google beat me to it! So I'll call it "Nest".

It totally abuses eval, closures, and scope chains, and so probably has no practical use.

However, I figured that all the other JavaScript libraries out there are models of perfection, so lets do the opposite, and let our eval hair down a bit!

Each module is nested as a closure within the previous module, so that it has closure access to all the public and private members of the previous modules loaded before it.

You could choose to export nothing, and have your application as the last module, so that it would be an entirely closed scheme.

It is only the bare bones (to illustrate).

The nesting scheme works as long as you have you don't have a two-way dependency between modules (which actually isn't that hard to achieve).

I have several modules of a few hundred functions and constructor functions apiece, which, load with little noticable lag, even on my old Windows 2000 laptop.

Have fun!

Click here to run the code

<html> 
<head>
<script>
function nest() 
{
	var NEST = this;
	var SELF = arguments.callee;
	var NEST_CURRENT_IMPORT_MODULE = this;
	var NEST_LAST_CLOSURE = closure;
	
	function exports(functionToExport)
	{
		var module = NEST_CURRENT_IMPORT_MODULE;

		// Just including the function-only code
		if (typeof functionToExport == "function")
		{
			var functionIdentifier /*: String*/ = Function_GetIdentifierFromString(functionToExport.toString());
			module[functionIdentifier] = functionToExport;
		}
		functionToExport.ownerModule = module;
	}

	function closure (jsSource) 
	{
		var returnValue;
		eval(jsSource);
		return returnValue;
	}
	exports(closure);

	function importModule(module) 
	{
		var moduleSource = module.toString();
		var identifier = Function_GetIdentifierFromString(moduleSource);
		var evalSource = moduleSource + "; var returnValue = new " + identifier + "();" + identifier + " = null;";
		var importedModule = NEST_LAST_CLOSURE(evalSource);
		NEST_LAST_CLOSURE = importedModule.closure;
		NEST[importedModule.nameSpace] = importedModule;
	}
	exports(importModule);

	function Function_GetIdentifierFromString(functionSource)
	{
		var funcPattern = /^\s*function\s+([A-Za-z0-9_$]+)\s*\(/;	
		var execResult = funcPattern.exec(functionSource);
		var functionIdentifier /*: String*/ = execResult[1];
		return functionIdentifier;
	}
	exports(Function_GetIdentifierFromString);
	
	function inspect(findName)
	{
		var source = "returnValue = " + findName;
		return NEST_LAST_CLOSURE(source);
	}
	exports(inspect);

	if (!SELF.booted)
	{
		SELF.booted = true;
		var boot = new SELF();
		window.nest = boot;
	}
}

function io()
{
	this.nameSpace = "io";
	NEST_CURRENT_IMPORT_MODULE = this;

	function closure (jsSource)	
	{
		var returnValue;
		eval(jsSource);
		return returnValue;
	}
	exports(closure);

	function ExportedFunctionFromIO()
	{
		alert("Hello from io");
	}
	exports(ExportedFunctionFromIO);
}

function dom()
{
	this.nameSpace = "dom";
	NEST_CURRENT_IMPORT_MODULE = this;

	function closure (jsSource)
	{
		var returnValue;
		eval(jsSource);
		return returnValue;
	}
	exports(closure);

	function ExportedFunctionFromDOM()
	{
		alert("Hello from dom");
		
		ExportedFunctionFromIO();
	}
	exports(ExportedFunctionFromDOM);
	
	function PrivateFunctionToInspect()
	{
		alert("You found me");
	}
	// Not exported
}

// Activate
nest();
nest.importModule(io);
nest.importModule(dom);

function test()
{
	nest.dom.ExportedFunctionFromDOM();
	nest.inspect("PrivateFunctionToInspect")();
}

</script>
</head>
<body>
<p onclick="test()">Click Here</p>
</body>
</html>

Comment(s)


Sorry, comments have been suspended. Too much offensive comment spam is causing the site to be blocked by firewalls (which ironically therefore defeats the point of posting spam in the first place!). I don't get that many comments anyway, so I am going to look at a better way of managing the comment spam before reinstating the comments.


Leave a comment ...


{{PREVIEW}} Comments stopped temporarily due to attack from comment spammers.