javascript - 如何在闭包中创建新变量

标签 javascript closures eval v8 ecmascript-2016

考虑这段代码

'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

所以,我有两个问题:

  1. 为什么它没有按预期创建变量 v
  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

请注意,评估始终是一个坏主意......

关于javascript - 如何在闭包中创建新变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45118893/

相关文章:

javascript - javascript私有(private)变量如何在原型(prototype)实现中工作

javascript - 将定时器 ID 放入其函数中

javascript - 替换第一次出现后的所有 x

javascript - 如何使用 Javascript 设置下拉列表的默认值

javascript - 使用光线转换器添加延迟

Swift 以编程方式为带有闭包的按钮创建函数

Ruby:按名称设置全局变量

javascript - iMacros 使用 EVAL 删除文本

java - C 中的 eval 函数结果为负

java - 如何让 Gson 的单转义与 Javascript 的特殊字符和符号的双转义一起使用?