如何在Javascript中声明动态局部变量

时间:2013-06-26 14:08:44

标签: javascript

我想动态创建一个局部变量。 JavaScript: Dynamically Creating Variables for Loops并不是我想要的。我不想要一个阵列。我想像局部变量一样访问它。

类似的东西:

    <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>

我尝试了以下代码。

    <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>

但是生成的变量在createVariables()之外是不可访问的。

现在,我有了这个解决方案。

    <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>

这很有效。但我正在寻找替代/更好的解决方案。没有eval可以做到吗?

编辑:7月4日

嗨,

我尝试了类似于@Jonathan建议的解决方案。

    <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>

一切正常。但它实际上是创建全局变量而不是在函数中创建变量。

传递给createVariables()函数的“self”是窗口。我不确定为什么会这样。我正在为自己分配功能范围。我不确定这里发生了什么。无论如何,在这种情况下创建全局变量。

如果我的问题不明确,

我所追求的是在调用者中创建局部变量。场景就像

1)我在一个函数里面。
2)我调用另一个函数,它返回一个map [此映射包含变量的名称和值]。
3)我想动态创建所有变量,如果它们尚未定义。如果已经定义了[global / local],我想更新它们。
4)创建这些变量后,我应该能够在没有任何上下文的情况下访问它们。[只是变量名称]

    <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>

7 个答案:

答案 0 :(得分:8)

根据您希望变量的范围,可以通过几种不同的方式实现。

全球范围

要将变量放在全局范围内,您可以使用window[varName]

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

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

试一试:http://jsfiddle.net/nLt5r/

请注意,全球范围是一个肮脏的公共场所。任何脚本都可以读取,写入或删除此范围内的变量。由于这个事实,您冒着破坏使用与您的变量名称相同的其他脚本的不同脚本或其他破坏您的脚本的风险。

功能范围(使用this

要在函数范围(this.varName)中创建变量,可以使用bind

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

试一试:http://jsfiddle.net/L4LbK/

根据您对绑定函数引用的处理方式,此方法稍微容易受到外部修改变量的影响。任何可以访问boundFunc的内容都可以使用boundFunc.varName = 'new value';来更改或引用值的值。这可能对您有利,具体取决于用例。

功能范围(使用参数)

您可以使用apply传递一组值作为参数:

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

试一试:http://jsfiddle.net/LKNqd/

由于参数本质上是短暂的,除了通过修改变量数组并重新调用函数之外,没有任何“外部”可以干扰或引用这些值。

全球范围为临时

这是一个小实用程序函数,它将临时使用全局范围。此函数对于也使用全局范围的代码是危险的 - 这可能会破坏其他脚本创建的变量,使用风险由您自负:

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

试一试:http://jsfiddle.net/X3p6k/3/

<强>文档

答案 1 :(得分:2)

以下是基于Chris Baker回答的工作示例:功能范围(使用参数)

&#13;
&#13;
    function myFn() {
      function keyList(params) {
        var str = '';
        for (var key in params) {
          if (params.hasOwnProperty(key)) {
            str += ',' + key;
          }
        }
        return str.length ? str.substring(1) : str;
      }

      function valueList(params) {
        var list = [];
        for (var key in params) {
          if (params.hasOwnProperty(key)) {
            list.push(params[key]);
          }
        }
        return list;
      }
      var params = {
        'var1': 'value1',
        'var2': 'value2'
      };
      var expr = 'document.write("Inside the function : " + var1 + "<br>")'
      var fn;
      eval('var fn = function(' + keyList(params) + '){' + expr + '};');
      fn(valueList(params));
    }

    myFn();
&#13;
&#13;
&#13;

答案 2 :(得分:2)

我编写了短代码片段,它将动态创建本地和全局变量

function createVar(name,dft){
 this[name] = (typeof dft !== 'undefined')?dft:"";
}

createVar("name1","gaurav"); // it will create global variable
createVar("id");// it will create global variable

alert(name1);
alert(id);
function outer(){
 var self = this;
  alert(self.name1 + " inside");
}
createVar.call(outer,"name1","saurav"); // it will create local variable
outer.call(outer); // to point to local variable.
outer(); // to point to global variable
alert(name1);
希望这会有所帮助 问候 Gaurav Khurana

答案 3 :(得分:1)

下面的示例演示 with 如何从对象中获取值。

www.newDomain.com/newParameter/newyork

但我想注意: with已被弃用!

答案 4 :(得分:0)

你需要这样的东西吗?

function createVariables(properties, context){
 for( var variable in properties){
    context[variable] = properties[variable ];
 }
}

因此,调用createVariables(properties, this)将使用properties中的值填充当前范围。


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

        createVariables(properties, this);

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

答案 5 :(得分:0)

因为你想要调用函数的范围将this传递给函数

var properties = new Object();
properties["var1"] = "value1";
properties["var2"] = "value2";
function createVariables(context) {
     for(i in properties) { 
         context[i] = properties[i];
     }   
}
createVariables(this);
console.log( var1 );

答案 6 :(得分:0)

这个答案或多或少与上面的几个答案相同,但这里有一个简化的样本,有和没有使用eval。首先使用eval(不推荐):

var varname = 'foo';  // pretend a user input that
var value = 42;
eval('var ' + varname + '=' + value);

另外,不使用eval:

var varname = prompt('Variable name:');
var value = 42;
this[varname] = value;

我希望这会有所帮助。

来源:ExpressiveAnnotations