Faking Context In Javascript's Function() Constructor

In my jQuery Template Markup Language (JTML) project, I needed a way to compile JTML templates down into Javascript functions such that they could be executed at any time in order to generate new HTML markup. This is a tricky problem because the JTML code makes references to non-scoped variables that have to be available in the rendering engine's context at the time that it executes. When I coded this project, the only solution that I could figure out at the time was to actually create a new Function() every time a template needed to be rendered. This, to some degree, defeats the purpose of compiling the rendering engine ahead of time. After thinking about this problem for a while, I wondered if I could leverage Javascript's apply() functionality to create dynamically-scoped, pre-compiled functions.

When you use the apply() or call() methods to change the execution context of a given function, all it really does is change the "this" reference; this has no effect on non-scoped variables, which will still be found by crawling up the function's closure chain. However, what if we had a function that checked for its own "this" context before it executed? If we created a function that appended this-scoped variables onto its local context before running, we should be able to dynamically change the available non-scoped variables simply by changing the function's context. That is exactly what I tried to do in the demo below:

<!DOCTYPE HTML>

<html>

<head>

<title>Javascript Function() With Context</title>

<script type="text/javascript" src="jquery-1.4.2.js"></script>

<script type="text/javascript">

// I am a proxy for the Function() constructor that prepends

// code to copy the function's context variables into the

// function local scope so that they may dynamically changed

// at the time of execution.

function FunctionContext( sourceCode ){

// Call and return the Function() constructor. Notice

// that if the THIS is not Window, we are VAR'ing the

// context variables into the function local scope.

return(Function(

"if (this != window){" +

"for (var __i in this ){" +

"eval( 'var ' + __i + ' = this[ __i ];' );" +

"}" +

"}" +

sourceCode

));

}

// -------------------------------------------------- //

// -------------------------------------------------- //

// Define a function that uses a variable that is not

// defined as part of the function source code.

var saySomething = FunctionContext(

"console.log( name + ', you\\\'re looking so hot!' );"

);

// -------------------------------------------------- //

// -------------------------------------------------- //

// Now, execute the saySomething() method in three different

// contexts, each of which changes the name.

saySomething.apply({

name: "Tricia"

});

saySomething.apply({

name: "Vicky"

});

saySomething.apply({

name: "Erika"

});

</script>

</head>

<body>

<!--- Intentionally left blank. --->

</body>

</html>

Here, I have created the function, FunctionContext(), which is essentially a proxy to Javascript's Function() constructor. All it does is prepend a bit of logic to the given source-code before it is passed off to the native Function() constructor. The extra logic checks the "this" context of the function; if the function's context is not the window object, indicating that it has been overridden with a call() or apply() method, all of the this-scoped values are var'd into the compiled function's local scope. In this way, any variable that was in the context at the time of execution is now available as a non-scoped value within the function's logic.

As you can see, through the use of apply(), I am changing the context of the compiled function for each execution. And, since the first part of that execution copies this-scoped variables into the local scope, the unscoped variable, "name," never causes an error.

I needed a way to dynamically change the variables that were available at the time of a function execution. If I just used the eval() function, I lose the benefit of pre-compiled optimization. If I use just the Function() constructor, I can't really figure out a way to change the available variables without using named arguments (which I may not even know ahead of time). By using both approaches together, however, I think I have found a mostly-elegant way to change the set of available local variables at the time of function execution.

Yes, interesting. But at the end it comes to question isn't it too expensive to use eval in such an extent. Probably it is possible to solve this using literal notation or exploating namespaces? I quess.