考虑这段代码
'use strict';
var factory = () => script => eval(script);
var closure = factory();
closure('var v = 0');
var val = closure('typeof v');
console.log(val);
这是我尝试实现它。我想创建一个闭包,然后允许用户在该闭包中创建一个新的局部变量。这甚至可能吗?
我在某处读到“native function'eval'甚至可以在本地执行上下文中创建一个新变量。”。那么,为什么它不适用于我的例子呢?我的猜测是因为函数完成执行并且函数结束后的变量数量无法更改,但我不确定。
我的示例脚本创建了一个闭包,并尝试在该闭包中声明并初始化新变量v
,并为其分配编号0
。我希望typeof v
的结果应为number
,但实际上undefined
。
所以,我有两个问题:
v
答案 0 :(得分:2)
嗯,它是本地范围的,但有点太本地
var factory = () =>{
return script =>{
//this is the scope. you cant access any variables outside of this.
eval(script);
};
//you want to eval here, which is impossible
};
你可以做很多hacky范围的事情来解决这个问题(在上下文中存储所有变量):
var factory = (context={}) => script =>{ with(context){ return eval(script); }};
您需要在创建时初始化所有局部变量:
var exec=factory({v:0, b:undefined});// note that you need to set a value explicitly {v,b} wont worm
然后按预期工作:
console.log(
exec("v"),//0
exec("v=2"),//2
exec("v"),//2
typeof v //undefined
);
http://jsbin.com/xibozurizi/edit?console
如果你不想那么深入,你唯一可以做的就是连接字符串:
var factory = code => concat => (eval(code),res=eval(concat),code+=concat,res);
// or shorter / more buggy
var factory = code => concat => eval(code+=";"+concat);
var exec=factory("var a=1;");
console.log(
exec("a;"),//1
exec("var b=a+1"),
exec("b"),//2
tyepof a, typeof b //undefined
);
http://jsbin.com/midawahobi/edit?console
上面的代码将多次运行字符串,这可能不需要。另一种方法:
var factory=code=>({
code,
run(c){
return eval(this.code+";"+c);
},
add(c){ this.code+=";"+c}
});
所以你可以做到
var exec=factory("var a='hello'");
exec.run("alert(a)")//alerts hello
exec.add("var b=a+' world'");
console.log(exec.code,exec.run("b"));//hello world, the upper alert isnt run again
http://jsbin.com/lihezuwaxo/edit?console
请注意,评估总是一个坏主意......
答案 1 :(得分:0)
您对[
{"idType":"ID_ISIN","idValue":"US4592001014"},
{"idType":"ID_WERTPAPIER","idValue":"851399","exchCode":"US"},
{"idType":"ID_BB_UNIQUE","idValue":"EQ0010080100001000","currency": "USD"},
{"idType":"ID_SEDOL","idValue":"2005973","micCode":"EDGX", "currency":"USD"}
]
的调用会创建一个新变量,并且会在调用的本地执行上下文中执行此操作。该上下文是内部该函数,因此它不会影响在之外的上下文,您调用eval()
。
一般来说,closure()
一般要严格避免。它使得优化变得困难(或不可能),因此优化器将忽略使用它的函数。在某些罕见的情况下它很有用,但声明一个新的局部变量并不像其中之一。
答案 2 :(得分:0)
你可以这样做
var factory = () => script => eval(script);
var closure = factory();
var v;
closure('v=20')