在新的Function构造函数中指定要用作全局作用域的对象?

时间:2018-02-02 04:26:59

标签: javascript function scope global

在使用new Function(...)创建函数时,Javascript中是否有一种方法可以指定要用作全局范围的对象?

例如,考虑一个字符串

  var str = "return foo()";  // user supplied, generated by a trusted program

我们可以用这个字符串创建一个函数,传入某些参数

  var fn = new Function(str);
  var result = fn() 

如果在全局范围中定义foo,则可以使用此选项,浏览器中为window或Node.js中为GLOBAL.global

但是有没有办法给这个新创建的函数一个对象,例如{foo: function() { return 42; }}并告诉它将其用作全局范围?

这里的动机是可能假定存在于全局范围内的可能函数的范围是未知的。我想使用ES6 Proxy定义一个对象,它为未预料到的函数提供默认实现,并将该对象传递给函数中的全局作用域。

我知道可以明确定义和传递特定的参数,例如

  var fn = new Function("foo", str);
  var result = fn(function() { return "bar"; })

但这不会起作用,因为我想处理我们没有预料到的方法。

也可以传入一个对象,例如

 var scope = { foo: function() { return 42; }
 var fn = new Function("scope", str);
 var result = fn(scope)

但这不起作用,因为字符串显示"return foo()"而不是"return scope.foo()"

Define a scope for javascript Function constructor

修改

@ChiragRavindra和@RobG的评论建议回答......

 var str = "return 'sand'+foo(); "  
 var o = {foo: function() { return "bar"}}
 var fn = new Function("obj", "with (obj) { " + str + "}")
 fn = fn.bind(o,o)
 fn(str) //==> "sandbar"

1 个答案:

答案 0 :(得分:2)

是的,你可以。定义一个Proxy,用函数解析每个属性。因此,要实现您的第二个示例,我们可以这样做:



function factory (string) {
  const callable = new Function(`with(this){${string}}`);

  return function fn (method) {
    return callable.call(new Proxy({}, {
      has () { return true; },
      get (target, key) { if (typeof key !== 'symbol') return method; }
    }));
  };
}

const fn = factory('return foo()');
const result = fn(() => 42);

console.log(result);