views:

165

answers:

5

I am attempting to declare a function outside of anonymous function but still have acess to all of the anonymous functions variables

Below is demonstrating what I'm talking about.

I just need to get rid of eval.

//Used to determine where the variable is being stored
var variableScope = "global";

(function(window){
        var variableScope = 'insideFunction',
        appearingToBeGlobalFunction = function(){
                alert("This Function appears Global but really isn't");
        };
        window["addFunction"]=function(funName,fun){
                //window[funName] = fun;  Doesn't work
                eval("window[funName]="+fun+";");
        }
})(window);

addFunction("alertTest",function(){
        alert(variableScope);
        appearingToBeGlobalFunction();
});

//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();

Edit: The goal of this question was to ultimately keep the global scope clean from tons of variables, but still have the convenience of accessing, set and calling as if they were global. I have concluded there is a way to doing what I'm after but it requires a deprecated functionality in javascript. Here is some example code showing how to accomplish the above without eval. This article discusses how to use "with".

var variableScope = "global";

var customScope = {
        variableScope : 'insideFunction',
        appearingToBeGlobalFunction : function(){
                alert("This Function appears Global but really isn't");
        }
};

function alertTest(){
        with(customScope){
             alert(variableScope);
             appearingToBeGlobalFunction();
        }
};

//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();​
A: 

you could force the variables to be in the global scope eg instead of var variableScope = 'insideFunction' you use window.variableScope = 'insideFunction'

Alex Nolan
The solution should not be to introduce more global variables.
Šime Vidas
+1  A: 
eval("window[funName]="+fun+";");

Oh dear Lord.

The reason this “works” is that you are converting the function fun (alertTest) into a string to put it in the eval argument.

It happens that in most desktop browsers, a native JS function's toString() result will be a string that looks like a function expression containing the same code as the original declaration. You're turning a function back into a string and re-parsing that string in the context of the new enclosing function, so the new function value is the same code but with a different closure.

However, it is not required that Function#toString work like this, and in some cases it won't. It is not safe to rely on function decomposition; avoid.

You can certainly only do this kind of horrific hackery using eval, although there is no reason the window[funName]= part has to be inside the eval. window[funName]= eval('('+fun+')'); would work equally well (badly).

I am attempting to declare a function outside of anonymous function but still have acess to all of the anonymous functions variables

Whyever would you do something crazy like that?

bobince
+1  A: 

You can't get rid of eval and still expect it to work. That's the only way to take a look at members of the scope after it's been "closed." I've messed around with something similar in the past, but I would never actually use it anywhere. Consider an alternate solution to whatever you're trying to accomplish.

CD Sanchez
A: 

Something like this?

<script type="text/javascript">
(function(window) {
    // create a scope we can reference:
    var scope = (function() {
        this.variableScope = 'insideFunction';
        this.appearingToBeGlobalFunction = function(){
            alert("This Function appears Global but really isn't");
        };
    })();
    window["addFunction"]=function(funName,fun){
        window[funName] = function() { fun.apply(scope, []); };
    }
})(window);

addFunction("alertTest",function(){
    alert(variableScope);
    appearingToBeGlobalFunction();
});

alertTest();

</script>
Brendon
Unfortunately the only reason this works is because `this` is bound to the global context. So you're defining those variables in the global context, not in the local context. That's why you can access them from `addFunction` on the outside. If you wanted to access the variables from the "scope", you would do `this.variableScope`. Also, you should change `var scope = (function() { ... })()` to `var scope = new function() { ... }`.
CD Sanchez
new function() {}? Why the new operator? It is a function expression...
Šime Vidas
Daniel is right. I would need to use `new` to create a new instance of the object. `scope` is not referencing the object, but the return value of the function. When it is executing this resolves to global, but with new this will resolve rightly to the current object.
Brendon
A: 

The goal of this question was to ultimately keep the global scope clean from tons of variables, but still have the convenience of accessing, set and calling as if they were global. I have concluded there is a way to doing what I'm after but it requires a deprecated functionality in javascript. Here is some example code showing how to accomplish the above without eval. This article discusses how to use "with".

var variableScope = "global";

var customScope = {
        variableScope : 'insideFunction',
        appearingToBeGlobalFunction : function(){
                alert("This Function appears Global but really isn't");
        }
};

function alertTest(){
        with(customScope){
             alert(variableScope);
             appearingToBeGlobalFunction();
        }
};

//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();​
Lime