Specify object to use as global scope in new Function constructor?

心不动则不痛 提交于 2020-01-06 08:04:28

问题


Is there a way in Javascript to specify an object to use as the global scope when creating a function using new Function(...)?

For instance, consider a string

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

we can create a function with this string, passing in certain arguments

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

This works if foo is defined in the global scope, either window in a browser or GLOBAL.global in Node.js.

But is there a way to give this newly created function an object, e.g. {foo: function() { return 42; }} and tell it to use that as the global scope?

The motivation here is the universe of possible functions that might be assumed to exist on the global scope is unknown. I'd like to define an object using ES6 Proxy that provides default implementations to unanticipated functions, and pass that object in to be used as the global scope within the function.

I know it's possible to explicitly define and pass in specific arguments, e.g.

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

but that won't work as i'd like to handle methods we didn't anticipate.

It's also possible to pass in an object, e.g.

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

but that won't work as the string says "return foo()" not "return scope.foo()"

Define a scope for javascript Function constructor

EDIT

Answer suggested from comments by @ChiragRavindra and @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:


Yes, you can. Define a Proxy that resolves every property with a function. So, to implement your second example, we can do this:

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);


来源:https://stackoverflow.com/questions/48575697/specify-object-to-use-as-global-scope-in-new-function-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!