考虑这段代码
'use strict';
var factory = () => script => eval(script);
var closure = factory();
closure('var v = 0');
var val = closure('typeof v');
console.log(val);
这是我为实现这一目标所做的尝试。我想创建一个闭包,然后允许用户在该闭包中创建一个新的局部变量。这可能吗?
我在某处读到“ native 函数‘eval’甚至可以在本地执行上下文中创建一个新变量。”。那么,为什么它在我的示例中不起作用?我的猜测是因为函数执行完毕并且函数结束后的变量数量无法更改,但我不确定。
我的示例脚本创建一个闭包,并尝试在该闭包中声明和初始化新变量v
,并为其分配数字0
。我预计 typeof v
的结果应该是 number
,但实际上是 undefined
。
所以,我有两个问题:
- 为什么它没有按预期创建变量
v
- 如何实际实现这一目标(工作示例是什么)?
最佳答案
嗯,它是本地范围的,但有点太本地化了
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
请注意,评估始终是一个坏主意......
关于javascript - 如何在闭包中创建新变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45118893/