Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 指定要在新函数构造函数中用作全局作用域的对象?_Javascript_Function_Scope_Global - Fatal编程技术网

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

Javascript 指定要在新函数构造函数中用作全局作用域的对象?,javascript,function,scope,global,Javascript,Function,Scope,Global,在Javascript中,有没有一种方法可以指定一个对象,在使用新函数(…)创建函数时用作全局作用域 例如,考虑字符串 var str = "return foo()"; // user supplied, generated by a trusted program 我们可以用这个字符串创建一个函数,传递某些参数 var fn = new Function(str); var result = fn() 如果在全局范围中定义了foo,则可以在浏览器中定义window,或在N

在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()”

编辑

根据@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"

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

函数工厂(字符串){
const callable=new函数(`with(this){${string}}`);
返回函数fn(方法){
返回callable.call(新代理({}{
has(){return true;},
get(target,key){if(typeof key!=='symbol')返回方法;}
}));
};
}
const fn=factory('return foo()');
const result=fn(()=>42);

控制台日志(结果)或可能有帮助?您似乎想要定义一个全局对象,而不是全局“范围”。这似乎不可能。with将把“范围”对象放在范围链的开头,而wan对象放在末尾。bind设置该值,该值与作用域链上的标识符解析无关,即它与作用域无关。这些问题通常使用模块模式或立即调用函数表达式(IIFEs)来解决
with
是我一直在寻找的想法。这个例子是一块宝石,真的很优雅。@虽然你的观点很受欢迎,但我必须强烈反对。我不会将任何包含
函数
构造函数或带有
语句的
,甚至是
代理的实现称为“优雅”。我会用“耐人寻味”或“俏皮”这样的词,但如果我在任何地方的生产代码中看到这种技术,我肯定会感到担心;而
with
仅仅是在现有范围的基础上增加了一个新范围。使
has
返回true可以防止大多数访问命中真正的全局范围,但由于扰乱了Javascript语义,可能会产生严重的连锁反应。而且它不是递归的,因此创建新函数将始终使用真正的全局范围。(我正试图解决与海报完全相同的问题。)顺便说一句,作为一个粗糙的性能黑客;创建一个新对象(这是您的新全局范围),其原型是上面的代理;然后将其用作
with
表达式。代理将仅对不在替换上下文对象中的属性调用,这些属性可能不是性能问题所在的属性。@DavidGiven我当然希望您不打算在生产环境中使用它。当你说诸如建议绩效改进之类的话时,听起来就像是在说。请记住,我并不认为这是一个值得生产的解决方案,一般的答案应该是“不,不要这样做,重构代码,这样就不会有未解决的引用需要处理。”