Как объявить динамическую локальную переменную в Javascript

Я хочу создать локальную переменную динамически. JavaScript: динамическое создание переменных для циклов - это не совсем то, что я ищу. Я не хочу массив. Я хочу получить к нему доступ как локальную переменную.

Что-то вроде:

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

EDIT: 04-July

Привет,

Я попробовал решение, подобное тому, что предложил @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>

Все это прекрасно работает. Но на самом деле он создает глобальные переменные вместо создания переменных в функции.

"self", переданный функции createVariables(), является окном. Я не уверен, почему это происходит. Я назначаю область действия самому себе. Я не уверен, что здесь происходит. В любом случае это создает глобальные переменные.

Если мой вопрос не ясен,

То, что я делаю, создает локальные переменные в вызывающем. Сценарий похож на

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>

Ответ 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/

Обратите внимание, что глобальный охват является грязным, общественным местом. Любой script может читать, записывать или удалять переменные в этой области. Из-за этого вы рискуете сломать другой script, который использует те же самые имена переменных, что и ваши, или другой script, разбивающий ваш.

Область действия функции (с помощью 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/

Documentation

Ответ 2

Вот рабочий пример, основанный на ответе Криса Бейкера: Область действия (с использованием аргументов)

    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

Я написал короткий фрагмент кода, который будет динамически создавать как локальную, так и глобальную переменную

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

Вам нужно что-то вроде этого?

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

так как вы хотите, чтобы область действия функции вызывала pass 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

В приведенном ниже примере показано, как с получением значения из объекта.

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

Но я хочу заметить: с устарел!

Ответ 7

Этот ответ более или менее совпадает с несколькими приведенными выше ответами, но здесь с упрощенным образцом, с использованием и без использования 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