【问题标题】:How to declare a dynamic local variable in Javascript如何在Javascript中声明一个动态局部变量
【发布时间】:2013-06-26 14:08:44
【问题描述】:

我想动态创建一个局部变量。 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”是window。我不确定为什么会这样。我将功能范围分配给自我。我不确定这里发生了什么。在这种情况下无论如何都是在创建全局变量。

如果我的问题不清楚,

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

1) 我在一个函数里面。
2)我调用另一个函数,它返回给我一个地图[这个地图包含一个变量的名称和值]。
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>

【问题讨论】:

  • 为什么?很难知道您要解决的真正问题是什么,但很容易猜测这是错误的解决方案。
  • 如果在函数中使用 var 关键字声明任何变量都是局部变量。尽量不要使用 eval,这确实看起来非常复杂。
  • 只是为了澄清这个问题:您是否试图在函数“内部”时在外部或全局范围内声明变量?或者您是否尝试将变量添加到函数调用的上下文中(这就是 this 关键字的用途)?
  • 我想在调用 createVariables() 函数的地方声明局部变量。我不想要全局变量。
  • @NimChimpsky:当然这很复杂,因为它是一个丑陋的解决方法。你能用更清楚的方式来做吗?我对此表示怀疑.. 另一方面,我不明白为什么我会这样做..

标签: javascript


【解决方案1】:

根据您希望变量具有的范围,这可以通过几种不同的方式完成。

全球范围

要将变量放在全局范围内,您可以使用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/

文档

【讨论】:

  • 我不能这样做....
    它告诉 Object [object global] 没有方法 'bind'
  • @PaulNibin 我不清楚您要在什么范围内执行此操作。这就是您要使用的脚本吗?如果是这样,您正在使用全局范围 - 不要绑定,使用 window[varName] 方法。如果该 sn-p 在函数内,则使用答案中的绑定方法。
  • 那个 sn-p 在一个函数中。如果我使用“this.foo”,我可以访问它。但实际上要创建一个局部变量。所以,我应该可以用“foo”访问。
  • this.foo 是只存在于函数内部的作用域。
  • @PaulNibin 查看编辑 -- apply 可能是你想要的?
【解决方案2】:

这是基于 Chris Baker 回答的工作示例:函数范围(使用参数)

    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();

【讨论】:

    【解决方案3】:

    我编写了短代码 sn-p,它将动态创建局部和全局变量

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

    希望这会有所帮助 问候 高拉夫·库拉纳

    【讨论】:

      【解决方案4】:

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

      var obj = { a : "Hello" }
      with(obj) {
        alert(a) // Hello
      }
      

      但我想注意:with 已弃用!

      【讨论】:

        【解决方案5】:

        这个答案或多或少与上面的几个答案相同,但这里有一个简化的示例,使用和不使用 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;
        

        我希望这会有所帮助。

        来源:https://www.rosettacode.org/wiki/Dynamic_variable_names#JavaScript

        【讨论】:

          【解决方案6】:

          因为您想要调用函数的范围,所以将 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 );
          

          【讨论】:

            【解决方案7】:

            你需要这样的东西吗?

            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>
            

            【讨论】:

            • 如何传递上下文?这里的上下文是什么?是“这个”对象吗?如果我设置 context[variable] = properties[variable],是不是在调用者上创建了一个局部变量?
            • @PaulNibin context 是对函数将创建变量的对象的引用。如果您传递this,则表示本地范围,但如果您的范围是全局范围,则您传递的是全局范围......
            • 这看起来是个不错的解决方案。在上下文中,如果变量已经可用(本地/全局),它将更新该变量。如果该变量不可用,它将创建一个新的局部变量。它是否正确?这正是我想要的
            • 您能否实际展示一下,按照您的预期工作? jsfiddle.net/AqXRG -- 不起作用。另外,@PaulNibin,此方法在创建变量之前不会检查变量是否已经存在。这将覆盖properties 中存在的任何内容。
            • 这与制作局部变量相反。它之所以有效,是因为在非严格模式下this 在上下文中它被传递 IS 全局对象,因此您正在向全局对象添加属性。请注意,运行此函数后,var1var2 随处可用,而不仅仅是在该函数中。这个 jsfiddle 表明:jsfiddle.net/goasfgp8
            猜你喜欢
            • 2011-03-22
            • 2019-02-13
            • 2017-12-22
            • 2018-11-23
            • 2011-09-29
            • 2011-03-10
            • 2011-11-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多