0

I want to create a closure dynamically. See code below for explanation.

function myFunction(){
    parentScopedVar(); //Would like to be able to call without using 'this'.
}


function myDynamicFunc(dynamicClosure){

    //What do I need to do here to dynamically create 
    //a var called 'parentScopedVar' that can be referenced from myFunction?

    myFunction.call(self);
}


myDynamicFunc(
         {
             parentScopedVar : function() { alert('Hello World'); }
         });
Alwyn
  • 8,079
  • 12
  • 59
  • 107

1 Answers1

1

Javascript uses lexical scope (based on where the code is declared), not dynamic scope.

If you are determined to try to do something that the language doesn't really encourage, you can force a string of code to be evaluated in your current execution context using eval(string of code here). In fact, you can do all sorts of odd things with eval(), but I'd much rather write code in a way that leverages the strengths of Javascript than to use a coding style that goes against the main design theme of the language (that's my opinion).

It's not entirely clear to me what problem you're trying to solve, but you can just pass a function as an argument and then call it via the argument from the called function.

// declare your function that takes a function reference an argument
function myFunction(callback) {
    // call the function that was passed
    callback();
}

function myDynamicFunc(){

    // declare a local function
    function myAlert() {
        alert('Hello World');
    }

    // call your other function and pass it any function reference
    myFunction(myAlert);
}

This will not pass an entire execution context. To do that, you'd have to package up the context in an object and pass a reference to the object, then dereference the properties from the object. That is typically how you pass an environment in JS.


You can use locally declared functions to provide access to parent scope from a callback (again lexical scope):

// declare your function that takes a function reference an argument
function doSomething(callback) {
    // call the function that was passed
    callback();
}

function myFunc() {
    var myLocal1 = "Hello";
    var myLocal2 = "World";

    function callback() {
        // when this is called, it has access to the variables of the parent scope
        alert(myLocal1 + " " + myLocal2);
    }

    doSomething(myFunc);
}

You can even use it as a lasting closure:

// declare your function that takes a function reference an argument
function doSomething(callback) {
    // call the function that was passed
    callback();
}

function myFunc() {
    var myLocal1 = "Hello";
    var myLocal2 = "World";

    function callback() {
        // when this is called, it has access to the variables of the parent scope
        // which are still alive in this closure even though myFunc has finished
        // executing 10 minutes ago
        alert(myLocal1 + " " + myLocal2);
    }

    // call the callback function 10 minutes from now, 
    // long after myFunc has finished executing
    setTimeout(callback, 10 * 60 * 1000);
}

Here are some reference articles on lexical and dynamic scope in Javascript:

Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?

Are variables statically or dynamically "scoped" in javascript?

What is lexical scope?

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Hmmm I can, but I just feel like avoiding dereferencing operators. eg. don't wanna see `myArg.parentScopedVar();`, I really just wanna call `parentScopedVar();` – Alwyn Aug 26 '14 at 22:37
  • @Alwyn - I don't understand what that comment means. My code example doesn't have an dereferencing operators. – jfriend00 Aug 26 '14 at 22:38
  • I meant I want to create something like an 'execution context', so that I won't have to pass parameter etc. I want it to magically make callback appear as if it was a variable local to myFunction. eg. C# LambdaExpression (Expression Tree). – Alwyn Aug 26 '14 at 22:44
  • @Alwyn - sorry, I guess I don't understand what you're trying to do. You can't magically give an externally defined callback function access to all your local variables. Scope in JS is defined by where the code is placed ([lexical scope](http://stackoverflow.com/questions/1047454/what-is-lexical-scope)). There is no dynamic scope. Folks generally use objects/properties and pass references to objects to handle that situation in JS. – jfriend00 Aug 26 '14 at 22:49
  • Scrounging your reply it seems possible. You can call `myFunction` from an eval string. eg. `var evalString = '(function(){'; for(var prop in dynamicClosure){ evalSring += 'var ' + prop + ' = ' + dynamicClosure[prop].toString() + ';\n';}; evalString += 'myFunction.call(self);})();'; eval(evalString);` <-- May be if you put this in I'll mark as answer. :D Thanks!!! Great discussion! – Alwyn Aug 26 '14 at 23:12
  • @Alwyn - yeah, if you want to get `eval()` involved, you can do all sorts of odd things. Sorry, but I won't be doing that in any of my code. IMO, it's much better to adapt code to the strengths of the language than try to make it do things it wasn't designed to do and doesn't do well. I added a short note about `eval()` to my answer. – jfriend00 Aug 26 '14 at 23:18