题
鉴于以下段的javascript在一个范围:
var x = 10;
function sayx() {
alert(x);
}
sayx();
你当然会期望一个信息框印刷'10',你可以做个多功能的嵌套的互动如何与'x'确定,因为当解决x是什么环境走的范围链。
你甚至可以做一个级别的重新编译'与eval注入新的范围运行时..例如:
var x = 10;
function sayx() {
alert(x);
}
function wrap(f) {
return eval('(function() { var x = 20;(' + f + ')(); })');
}
wrap(sayx)();
这是因为,该功能将有其toString功能称其将返回'原始'源..因此,我们基本上创建一个包裹版本的功能,有一个新的范围,复盖x。结果将是一个警报箱,印'20"而不是"10'.
然而,从表面上看,这可能会出现工作,但范围链被破坏,下一项链不再是一样的,因为功能'f'的定义现在在一个不同的位置。。更糟糕的是,范围链它具有继承能包含许多文献中调用的功能不应该有访问。
因此,有更多的支持,具有可操作性的方式注射范围的项目?是这样的:
function withScope(f, scope) { ??? }
---
var x = 10, y = 10;
function dothemath() {
alert(x + y);
}
var haxthemath = withScope(dothemath, { x: 9000 });
haxthemath(); // 9010 not 20
我猜答案是"不",有些人可能认为有"安全"问题与诸如注射范围,但考虑到你可以做的伎俩无论如何(尽管受到严重破碎)我不觉得它是...
这样的好处是,可以基本上是假的你自己的伪变量。
在此先感谢。
编辑,只是澄清一点,想象一下我想'withScope'功能,具有下列范围链:
Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }
我希望能够得到一个功能返回,有效地也有同样的链+范围,我提供..即:
withScope(somefunc, { foo: 'bar' })
会给我
Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }
Ext scope - { foo = 'bar' }
所有现有常设的变量会被发现的因为我的扩展范围并没有说任何关于他们。
解决方案
如果你是指由范围的地方变量的功能和/或闭幕,我认为答案是否定的。
你可以改变的范围 this
关键字,通过使用函数.呼吁(范围、arg1,...)或函数.申请(范围、[arg1,...]);这可能是一起使用原型,以建立类似的链作为你的描述-如果有什么不找到对象的自己的特性,它在其原型。如果财产是不存在的,下一个原型链中的使用等。
其他提示
回答我觉得你寻找的是建在"与"发言。
然而,我不会推荐使用它,因为它已过时,并将很可能不存在的写法6
唯一其它的方式我觉得你可以做这样的事情是从内部主机应用程序本身,操纵javascript环境。或者,如果你使用犀牛,你其实可以做到这一点从内部javascript,因为之间的链接Java api和Javascript只是无缝在犀牛。当史蒂夫yegge第一个指出,它吹我的脑海里。操纵javascript从外javascript,但从内部javascript!它是天才!
如果你困在一个浏览器的环境中,也许你可以使用一个javascript解释javascript编写的,例如水仙。
也许使用javascript是建立在 toString
方法的功能吗?
function withScope(f, scope) {
var toExec = "";
for (var prop in scope) {
toExec += "var " + prop + " = scope['" + prop + "'];"
}
toExec += "f = (" + f.toString() + ")";
eval(toExec);
return f;
}
var x = 10;
var f = function() {
console.log(x);
};
withScope(f, {x: 20})();
这似乎是一个坏主意,虽然...
你如果想玩范围内你可能会喜欢的 let
声明中提供的Javascript1.7. 最近版本的火狐支持 let
.