Как объявить динамическую локальную переменную в 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