Объявление переменной выше по цепочке - PullRequest
3 голосов
/ 12 января 2011

Я сомневаюсь, что это возможно, но я бы хотел попробовать.

Я бы хотел написать функцию, которая вводит новые переменные в область действия вызывающей стороны .

Цель состоит в том, чтобы сделать что-то вроде этого:

(function() {
    var x = {a: 5, b:6};
    console.log(typeof a, typeof b); // prints: undefined undefined
    magicImport(x);
    console.log(a, b); // prints: 5 6
})();

// Variables are not in global scope
console.log(typeof a, typeof b); // prints: undefined undefined

Если magicImport(x) делает что-то вроде

eval("var a = x.a; var b = x.b;");

это не очень помогает, поскольку область действия a и b будет ограничена внутри magicImport.

И конечно же

eval("a = x.a; b = x.b;");

не годится, так как это изменит глобальный объект.

Есть ли способ eval кода в более высоком объеме?

EDIT : Цель, если она не ясна, - создать функцию, которая может импортировать содержимое пространства имен без загрязнения глобальной области и без необходимости помещать эти импортированные объекты новый контейнерный объект.

Ответы [ 5 ]

3 голосов
/ 12 января 2011

Не делай этого.Если вы не хотите оказаться в кошмаре обслуживания.

Если я вызываю функцию, я хочу знать, какие у нее побочные эффекты, что, если импортируемый материал изменяется?Я сломаю все.Я с трудом представляю необходимость в таком магически управляемом, не поддерживаемом коде, если вам действительно нужно импортировать вещи, возвращать объект и использовать его свойства, но не выполнять магию ограниченного объема, поскольку это не будет работать с замыканиями или другими полезными функциямиязыка.

2 голосов
/ 12 января 2011

Я не уверен, что это то, что вам нужно, но вы можете просто использовать оператор with:

function() {
    var x = {a: 5, b:6};
    console.log(typeof a, typeof b); // prints: undefined undefined
    with(x) {
        console.log(a, b); // prints: 5 6
    }
}

В любом случае, так как это изменит так называемую цепочку областей видимости (подталкивая все свойствазаранее), любой другой вызов в операторе with станет медленнее.Это одна из причин, почему не рекомендуется использовать его.(не рекомендуется в ES5 ES5 в строгом режиме в любом случае)

1 голос
/ 12 января 2011

Как вы заметили, вам нужно выполнить eval, но вы должны оценить его в том объеме, который они должны определить. Нет возможности отложить вызов eval. magicImport должен создать строку для eval'd:

(function() {
    var x = {a: 5, b:6};
    console.log(typeof a, typeof b);  // output: undefined undefined
    eval(magicImport(x));
    console.log(a, b);                // output: 5 6
})();

// Variables are not in global scope
console.log(typeof a, typeof b);      // output: undefined undefined

function magicImport(x){
    return "var a=" + x.a + ",b=" + x.b ;
}

Альтернативой было бы пропустить вызов функции и использовать цикл. Вместо eval(magicImport(x)); вы можете заменить его на:

for(prop in x){eval("var " + prop + "=" + x[prop]);}

или

 var str = "";
 for(prop in x){str + = "var " + prop + "=" + x[prop] + ";" ;}
 eval(str);
1 голос
/ 12 января 2011

Я очень сильно подозреваю, что то, что вы хотите сделать, невозможно в JavaScript.Нет даже способа сослаться на на встраиваемые области.

Я не теоретик языка программирования, но я написал много программного обеспечения.Что-то в этой концепции просто кричит мне "плохая идея".Было бы странно, если бы функции вводили новые символы, как это ни странно, и было бы очень трудно понять программу.

Трудно понять, почему то, что вы хотите сделать, лучше, чем просто выбирать вызывающегохранить значение.Возможно, такие функции, как множественное назначение, сделают вас счастливее:

var x = { a: null, b: null };

// made up syntax here
<< x.a, x.b >> = magicFunction();

, где "magicFunction" каким-то образом вернет два значения.Но поскольку в Javascript уже есть объектная нотация, это не кажется мне слишком убедительным.

0 голосов
/ 12 января 2011

Это не много о сферах; Вы пытаетесь скопировать свойства в переменные с одинаковым именем.

Тем не менее, вот мой выстрел в это:

function magicImport(o) {
    for(property in o) {
        window[property] = o[property];
    }
}
...