Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare a dynamic local variable in Javascript

Tags:

javascript

I want to create a local variable dynamically. JavaScript: Dynamically Creating Variables for Loops is not exactly what I am looking for. I dont want an array. I want to access it like a local variable.

Something like:

    <script type="text/javascript">
        var properties = new Object();
        properties["var1"] = "value1";
        properties["var2"] = "value2";

        createVariables(properties);

        function createVariables(properties)
        {
            // This function should somehow create variables in the calling function. Is there a way to do that?
        }
        document.write("Outside the function : " + var1 + "<br>");
        document.write("Outside the function : " + var2 + "<br>");
    </script>

I tried the following code.

    <script type="text/javascript">
        var properties = new Object();
        properties["var1"] = "value1";
        properties["var2"] = "value2";

        createVariables(properties);

        function createVariables(properties)
        {
            for( var variable in properties)
            {
                try
                {
                    eval(variable);
                    eval(variable + " = " + properties[variable] + ";");
                }
                catch(e)
                {
                    eval("var " + variable + " = '" + properties[variable] + "';");
                }
            }
            document.write("Inside the function : " + var1 + "<br>");
            document.write("Inside the function : " + var2 + "<br>");
        }
        document.write("Outside the function : " + var1 + "<br>");
        document.write("Outside the function : " + var2 + "<br>");
    </script>

But the generated variables are not accessible outside the createVariables().

Now, I have this solution.

    <script type="text/javascript">
        var properties = new Object();
        properties["var1"] = "value1";
        properties["var2"] = "value2";

        function createVariables(properties)
        {
            var str = "";
            for( var variable in properties)
            {
                str += "try{";
                str += "eval('" + variable + "');";
                str += "eval(\"" + variable + " = properties['" + variable + "'];\");";
                str += "}";
                str += "catch(e){";
                str += "eval(\"var " + variable + " = properties['" + variable + "'];\");";
                str += "}";
            }
            return str;
        }

        eval(createVariables(properties));
        document.write("Outside the function : " + var1 + "<br>");
        document.write("Outside the function : " + var2 + "<br>");
    </script>

This works. But I am looking for an alternative/better solution. Is it possible to do it without eval?

EDIT: 04-July

Hi,

I tried a solution similar to what @Jonathan suggested.

    <script type="text/javascript">

    var startFunc = function(){
        var self = this;

        self.innerFunc = function innerFunc(){
            var properties = new Object();
            properties["var1"] = "value1";
            properties["var2"] = "value2";
            properties["var3"] = "value3";

            function createVariables(caller, props) {
                 for(i in props) { 
                     caller[i] = props[i];
                 }  
                 caller.func1();
            }
            createVariables(self, properties);
            console.log( var1 );
        }

        self.func1 = function func1(){
            console.log( "In func 1" );
            console.log( var2 );
        }

        innerFunc();
        console.log( var3 );
    }

    startFunc();


    </script>

This all works fine. But it is actually creating global variables instead of creating the variables in the function.

The "self" passed to the createVariables() function is window. I am not sure why it is happening. I am assigning the function scope to the self. I am not sure what is happening here. It is anyway creating global variables in this case.

If my question is not clear,

What I am after is creating local variables in the caller. The scenario is like

1) I am inside a function.
2) I invoke another function which returns me a map[This map contains name and value of a variable].
3) I want to dynamically create all the variables, if they are not already defined. If they are already defined [global/local], I want to update them.
4) Once these variables are created, I should be able to access them without any context.[Just the variable name]

    <script type="text/javascript">
        function mainFunc()
        {
            var varibalesToBeCreated = getVariables();
            createVariables(varibalesToBeCreated);

            alert(var1);
            alert(var2);
        }

        function createVariables(varibalesToBeCreated)
        {
            // How can I implement this function, 
            // such that the variables are created in the caller? 
            // I don't want these variables this function.
        }

        function getVariables()
        {
            var properties = new Object();
            properties["var1"] = "value1";
            properties["var2"] = "value2";  
        }


        mainFunc();
    </script>
like image 623
Paul Nibin Avatar asked Jun 26 '13 14:06

Paul Nibin


People also ask

What is dynamic local variable?

In a high-level language, non-static local variables declared in a function are stack dynamic local variables by default. Some C++ texts refer to such variables as automatics. This means that the local variables are created by allocating space on the stack and assigning these stack locations to the variables.

What is a dynamic variable JavaScript?

Dynamic variables compute their own values by executing statements and logical expressions. A dynamic variable assigns itself the result of a calculation or operation. The dynamic variable types are dynamic string, dynamic number, and dynamic True/False (Boolean).


1 Answers

Depending on the scope you'd like the variables to have, this could be accomplished in a few different ways.

Global scope

To place the variables in the global scope, you could use window[varName]:

function createVariables(variables) {
    for (var varName in variables) {
        window[varName ] = variables[varName ];
    }
}

createVariables({
    'foo':'bar'
});
console.log(foo); // output: bar

Try it: http://jsfiddle.net/nLt5r/

Be advised, the global scope is a dirty, public place. Any script may read, write, or delete variables in this scope. Because of this fact, you run the risk of breaking a different script that uses the same variable names as yours, or another script breaking yours.

Function scope (using this)

To create variables in a function's scope (this.varName), you can use bind:

var variables = {
    'foo':'bar'
};
var func = function () {
    console.log(this.foo);
};
var boundFunc = func.bind(variables);
boundFunc(); // output: bar

Try it: http://jsfiddle.net/L4LbK/

Depending on what you do with the bound function reference, this method is slightly vulnerable to outside modification of the variables. Anything that can access boundFunc can change or refer to the value of the values by using boundFunc.varName = 'new value'; This may be to your advantage, depending on use case.

Function scope (using arguments)

You can use apply to pass an array of values as arguments:

var variables = [
    'bar'
];
var func = function (foo) {
    console.log('foo=', foo);
};
func.apply(null, variables);

Try it: http://jsfiddle.net/LKNqd/

As arguments are ephemeral in nature, nothing "outside" could interfere with or refer back to the values, except by modifying the variable array and re-calling the function.

Global scope as temporary

And here's a small utility function that will make temporary use of the global scope. This function is dangerous to code that also uses the global scope -- this could blast over variables that other scripts have created, use at your own risk:

var withVariables = function(func, vars) {
   for (var v in vars){
       this[v] = vars[v];
   }
   func();
   for (var v in vars){
       delete this[v];
   }
};

// using an anonymous function
withVariables(
    function () {
        console.log('anonymous: ', foo);   
    },
    {
        'foo':'bar'   
    }
); // output: bar

// using a function reference
var myFunction =function () {
    console.log('myFunction: ', foo);   
};
withVariables(myFunction, {
    'foo':'bar'   
}); // output: bar

console.log(foo); // output: undefined

Try it: http://jsfiddle.net/X3p6k/3/

Documentation

  • bind on MDN - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
  • apply on MDN - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
  • window on MDN - https://developer.mozilla.org/en-US/docs/Web/API/Window
like image 66
Chris Baker Avatar answered Oct 02 '22 11:10

Chris Baker