在范围链中更高的位置声明变量

时间:2011-01-12 15:21:15

标签: javascript scope eval

我怀疑这是可能的,但我想试一试。

我想编写一个函数,将新变量引入其调用者的范围

目标是做这样的事情:

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

这实际上没有用,因为ab的范围将仅限于magicImport内。

当然

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

不好,因为它会修改全局对象。

在更高的范围内有eval代码吗?

编辑:如果不清楚,目标是创建可以导入命名空间内容而不会污染全局范围的函数,而不必放置那些导入的对象进入一个新的容器对象。

5 个答案:

答案 0 :(得分:3)

不要这样做。除非你想最终陷入维持噩梦。

如果我调用一个函数我想知道它有什么副作用,如果导入的东西发生了变化怎么办?我会破坏一切。我很难想象是否需要这样的魔法驱动,不可维护的代码,如果你真的需要导入东西,返回一个对象并使用它的属性,但不要做范围魔术,因为这不适用于闭包或其他好的功能语言。

答案 1 :(得分:2)

我不确定这是否是您想要的,但您可以使用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严格模式中弃用)

答案 2 :(得分:1)

我非常强烈怀疑你想要做的事情在JavaScript中是不可能的。 引用甚至没有方法来封闭范围。

我不是编程语言理论家,但我已经编写了很多软件。关于这个概念的东西只是尖叫着#34;糟糕的主意"对我来说。让函数不假思索地引入新符号会非常奇怪,这会让你很难理解一个程序。

很难理解为什么你想要做的比简单地让调用者选择存储值的位置更好。也许像多项任务这样的功能会让你更开心:

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

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

其中&#34; magicFunction&#34;会以某种方式返回两个值。但是因为Javascript已经有了一个对象表示法,这对我来说似乎不太引人注目。

答案 3 :(得分:1)

如您所述,您需要eval,但您必须在他们需要定义的范围内进行评估。没有办法推迟调用eval。 magicImport必须构建要评估的字符串:

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

答案 4 :(得分:0)

这与范围不太相关;您正试图将属性复制到碰巧具有相同名称的变量中。

然而,这是我的镜头:

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