Як оголосити динамічну локальну змінну в 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 + "
"); document.write("Outside the function : " + var2 + "
"); </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 + "
"); document.write("Inside the function : " + var2 + "
"); } document.write("Outside the function : " + var1 + "
"); document.write("Outside the function : " + var2 + "
"); </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 + "
"); document.write("Outside the function : " + var2 + "
"); </script>

Це працює. Але я шукаю альтернативне/краще рішення. Чи можна це зробити без eval?

EDIT: 04-липня

Привіт,

Я спробував рішення, подібне до того, що запропонував Джонатан.

    <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) 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>
12
@PaulNibin Рішення eval є єдиним, що дійсно працює.
додано Автор Jacques de Hooge, джерело
будь-яка змінна є локальною, якщо вона оголошена в межах функції за допомогою var. Намагайтеся не використовувати eval, це дійсно виглядає значно складніше.
додано Автор NimChimpsky, джерело
Чому? Важко знати, яку реальну проблему ви намагаєтеся вирішити, але легко вгадати, що це неправильне рішення.
додано Автор Denys Séguret, джерело
Просто шукайте роз'яснення питання: чи намагаєтесь ви оголосити змінні у зовнішній або глобальній області, а "всередині" функції? Або ви намагаєтеся додати змінні до контексту виклику функції (саме для цього використовується слово this )?
додано Автор Qantas 94 Heavy, джерело
@NimChimpsky: Звичайно, це складно, тому що це непривабливе рішення. Чи можете ви зробити це більш чітко? Я сумніваюся. З іншого боку, я не розумію, чому я коли-небудь це роблю ..
додано Автор Karoly Horvath, джерело
@Chris: Просто оберніть код, який він розмістив у межах функції.
додано Автор Karoly Horvath, джерело
Фрагменти, які ви показуєте тут, Paul, не є "локальними змінними" - ви показуєте код лише за допомогою глобальної області. Різниця в підході залежить від бажаного обсягу. Я думаю, що нам потрібно бачити реальний випадок використання замість неясного прикладу, якщо ви не отримуєте потрібних відповідей.
додано Автор Chris Baker, джерело
Я хочу оголосити локальні змінні, у яких викликається функція createVariables (). Я не хочу глобальних змінних.
додано Автор Paul Nibin, джерело

7 Відповіді

Залежно від обсягу, який ви хочете мати змінними, це може бути виконано декількома різними способами.

Глобальний обсяг

Щоб розмістити змінні в глобальній області, можна скористатися вікном [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/

Радимо, глобальна сфера - це брудне, громадське місце. Будь-який скрипт може читати, писати або видаляти змінні в цій області. У зв'язку з цим ви ризикуєте зламати інший сценарій, який використовує ті ж імена змінних, що і ваші, або інший скрипт, який порушує ваш.

Область функції (за допомогою цього )

Щоб створити змінні в області функції ( this.varName ), можна скористатися 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/

Залежно від того, що ви робите з посиланням на пов'язану функцію, цей метод трохи вразливий до зовнішньої модифікації змінних. Все, що може отримати доступ до boundFunc , може змінювати або посилатися на значення значень за допомогою boundFunc.varName = 'new value'; Це може бути вашим перевагою, залежно від використання випадок.

Область функції (використовуючи аргументи)

За допомогою apply можна передавати масив значень як аргументи:

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

Try it: 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

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

Документація

8
додано
P.S. можна використати літерали об'єкта або масиву {} / [] , як це було зроблено в моїх зразках замість формального методу new Object() для коротший код :)
додано Автор Chris Baker, джерело
@PaulNibin Ознайомтеся з редагуванням - apply може бути те, що ви хочете?
додано Автор Chris Baker, джерело
this.foo - це область, яка існує тільки в межах цієї функції.
додано Автор Chris Baker, джерело
@PaulNibin Мені не зрозуміло, якою сферою ви намагаєтеся це зробити. Це буквально скрипт, який ви використовуєте? Якщо так, ви використовуєте глобальну область дії - не прив'язуйте, використовуйте метод window [varName] . Якщо цей фрагмент знаходиться у межах функції, ви використовуєте метод прив'язки з відповіді.
додано Автор Chris Baker, джерело
Я не можу це зробити .... <script type = "text/javascript"> var properties = new Object (); властивості ["var1"] = "value1"; властивості ["var2"] = "value2"; this.bind (властивості); document.write ("За межами функції:" + var1 + "
"); document.write ("За межами функції:" + var2 + "
"); </script>
Вона повідомляє Object [object global] не має методу 'bind'
додано Автор Paul Nibin, джерело
Цей фрагмент є функцією. Якщо я використовую "this.foo", я можу отримати доступ до неї. Але насправді потрібно створити локальну змінну. Отже, я повинен мати доступ до "foo".
додано Автор Paul Nibin, джерело
Спасибі Кріс, за вказівку всіх цих способів передачі аргументів функції. Але те, що я після цього, створює локальні змінні у дзвінка. Сценарій схожий на 1) Я перебуваю у функції. 2) Я викликаю іншу функцію, яка повертає мені карту [Ця карта містить ім'я та значення змінної]. 3) Я хочу динамічно створювати всі змінні, якщо вони ще не визначені. Якщо вони вже визначені [global/local], я хочу їх оновити. 4) Як тільки ці змінні будуть створені, я повинен мати доступ до них без будь-якого контексту. [Просто назва змінної]
додано Автор Paul Nibin, джерело

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

<div class="snippet" data-lang="js" data-hide="false"> <div class="snippet-code">

    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 + "
")' var fn; eval('var fn = function(' + keyList(params) + '){' + expr + '};'); fn(valueList(params)); } myFn();
</div> </div>
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);

сподіваюся, що це допоможе З повагою Гаурав Хурана

2
додано

оскільки ви бажаєте, щоб функція була викликана, передайте її функції 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 );
0
додано

Вам потрібно щось подібне?

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

Таким чином, виклик як createVariables (властивості, це) заповнить поточну область значенням із властивостей .


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

        createVariables(properties, this);

        document.write("Outside the function : " + var1 + "
"); document.write("Outside the function : " + var2 + "
"); </script>
0
додано
@PaulNibin контекст - це посилання на об'єкт, у якому функція створить змінні. Якщо ви передаєте this , це означає локальну область, але якщо ваша сфера є глобальною, ви передаєте глобальну ...
додано Автор Jonathan Naguin, джерело
@PaulNibin Це правильно.
додано Автор Jonathan Naguin, джерело
@Chris Ви маєте рацію, якщо ви показуєте, що я не охоплюю його в коді (це не в моїй відповіді)
додано Автор Jonathan Naguin, джерело
Не могли б ви показати це в дії, працюючи, як ви очікуєте? jsfiddle.net/AqXRG - не працює. Крім того, @PaulNibin, цей метод не перевіряє, чи існує змінна до її створення. Це буде оратити все, що існує з будь-яким іншим властивістю властивостей .
додано Автор Chris Baker, джерело
Чи можете ви показати будь-який варіант використання цього коду?
додано Автор Chris Baker, джерело
Це є протилежністю при створенні локальних змінних. Вона працює тільки тому, що в нетримальному режимі this у контексті, що передається IS глобальному об'єкту, і ви додаєте властивості до глобального об'єкта в результаті. Зауважте, що після запуску цієї функції var1 і var2 доступні скрізь, а не тільки в цій функції. Ця jsfiddle показує, що: jsfiddle.net/goasfgp8
додано Автор Jimbo Jonny, джерело
Нижче наведено робочий приклад: jsfiddle.net/AqXRG/6
додано Автор jpadvo, джерело
Привіт, я спробував вище рішення.
додано Автор Paul Nibin, джерело
Це виглядає як гарне рішення. У контексті, якщо змінна вже доступна (локальна/глобальна), вона буде оновлювати змінну. Якщо змінна недоступна, вона створить нову локальну змінну. Це правильно? Це саме те, що я хочу
додано Автор Paul Nibin, джерело
Як пройти контекст? Який тут контекст? Це "цей" об'єкт? Якщо я встановлюю контекст [змінну] = властивості [змінну], чи створює він локальну змінну у виклику?
додано Автор Paul Nibin, джерело

Ця відповідь більш-менш така ж, як кілька відповідей вище, але тут з спрощеним зразком, з використанням і без використання 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;

Я сподіваюся, що це допоможе.

Source: https://www.rosettacode.org/wiki/Dynamic_variable_names#JavaScript

0
додано

Наведений нижче приклад демонструє, як з отримує значення від об'єкта.

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

But I want to notice: with is deprecated!

0
додано
ІТ КПІ - JavaScript
ІТ КПІ - JavaScript
504 учасників

співтовариство javascript розробників в Telegram