扩展javascript功能范围
是否可以动态扩展javascript功能范围?我尝试没有成功如下:扩展javascript功能范围
function foo()
{
var bar = 12;
return function(x)
{
return eval(x);
}
}
var e = foo();
console.log(e("bar")); // 12
console.log(e("bar = 42;")); // 42
console.log(e("bar")); // 42
console.log(e("var baz = 99;")); // undefined
console.log(e("baz")); // ReferenceError: baz is not defined
然而,如果我从线baz = 99
删除var
那么巴兹变量变成一个全球性的(这使我感觉良好):
...
console.log(e("baz = 99;")); // 99
console.log(e("baz")); // 99
console.log(baz); // 99 (so baz is just a global)
每次你打电话e("var baz = 4")
,它创建一个函数调用堆栈上的变量,因此它不会在下次调用时可用。
如果您需要动态添加变量到范围,我会使用Rayno的建议,使用地图。 http://jsfiddle.net/UVSrD/
function foo()
{
var scope = {};
return function(x)
{
return eval(x);
}
}
var e = foo();
console.log(e("scope.bar = 12")); // 12
console.log(e("scope.bar")); // 12
console.log(e("scope.baz = 14")); // 14
console.log(e("scope.baz;")); // 14
// Not a global
console.log(typeof scope) // undefined
我明白为什么评估'var baz = 99;'没有工作......问题在于我想访问的范围是外部范围,而不是'foo'返回的函数。使用本地对象是一个选项,但意味着每次访问都使用双重查找(首先查找“范围”并查找变量或函数)。 – 6502 2012-04-03 20:19:48
是的,作用域链是词法,所以你不能修改它。 – 2012-04-03 20:21:45
我接受了,因为你最后的评论对我有意义。太糟糕了,没有一个预定义的词法变量绑定到封闭范围......可能这是故意的,因为使用固定大小的词法范围简化了实现或允许一些优化(但是我没有看到它们中的很多,示例eval必须能够访问所有词汇,实现*关闭整个范围内的闭包,而不仅仅是关闭的变量)。 – 6502 2012-04-03 23:11:18
你创造使用此代码封闭:
function foo()
{
var bar = 12;
return function(x)
{
return eval(x);
}
}
当你在酒吧通过你的覆盖已经被启动,以12杆的变量,我不知道是什么你试图完成,但使用闭包将保留外部函数变量。
是的我知道我正在创建一个闭包,第二个'eval'正在修改一个捕获的变量。问题是,如果可能稍后添加更多的“捕获变量”和本地函数。 – 6502 2012-04-03 19:40:14
Eval将在所调用的任何位置运行。您看到的行为是因为在此行上:
console.log(e("var baz = 99;")); // undefined
您在返回的函数的本地范围内创建var baz = 99。 var name = value的返回值;不是什么,你会得到未定义的。当您随后致电
console.log(e("baz")); // ReferenceError: baz is not defined
您返回一个新函数,其中baz尚未定义。
这是有点酷:http://www.bennadel.com/blog/1926-Exploring-Javascript-s-eval-Capabilities-And-Closure-Scoping.htm
事实上,当我做了这个实验后,我才明白为什么评估'var baz'不起作用。我的问题是,如果有可能逃离一个层次并进入包含范围。 – 6502 2012-04-03 20:09:10
我不认为这是可能的,因为这涉及修改范围两个层面。据我所知,没有办法直接影响范围。你可以创建一个新的对象并返回它,但我不相信你可以直接改变它创建的范围。 – 2012-04-03 20:45:05
为什么你会想这个,这是肮脏的地狱 – Raynos 2012-04-03 19:32:56
@Raynos:呵呵呵......可能是,但我不认为这是可怕的:我在写一个有趣的编译器瞄准的Javascript和实现模块我想知道如果使用函数作用域是一个可行的选项,同时保持模块“打开”(即允许从多个位置向模块添加名称,而不必一次性定义所有名称并使模块“密封“之后) – 6502 2012-04-03 19:37:19
您是否考虑过使用对象?您不能使用函数作用域作为模块的容器 – Raynos 2012-04-03 19:53:21