Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.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_Node.js - Fatal编程技术网

Javascript 创建助手函数以在隔离作用域中运行函数

Javascript 创建助手函数以在隔离作用域中运行函数,javascript,node.js,Javascript,Node.js,此代码适用于: it.cb(h => { console.log(h); h.ctn(); }); it.cb(new Function( 'h', [ 'console.log(h)', 'h.ctn()' ] .join(';') )); 这两个测试用例基本相同。但是用这样的数组构造字符串很麻烦,而且无法进行静态分析。所以我想做的是这样的: it.cb(isolated(h => { c

此代码适用于:

  it.cb(h => {
    console.log(h);
    h.ctn();
  });

  it.cb(new Function(
    'h', [
      'console.log(h)',
      'h.ctn()'
    ]
    .join(';')
  ));
这两个测试用例基本相同。但是用这样的数组构造字符串很麻烦,而且无法进行静态分析。所以我想做的是这样的:

 it.cb(isolated(h => {
    console.log(h);
    h.ctn();
 }));
其中,isolated是一个助手函数,类似于:

const isolated = function(fn){
   const str = fn.toString();
   const paramNames = getParamNames(str);
   return new Function(...paramNames.concat(str));
};
最大的问题是
Function.prototype.toString()
提供了整个函数。有人知道从函数的字符串表示中获取函数体的好方法吗

更新:PRoberts问这是为了什么,目的很简单:

 const foo = 3;

 it.cb(isolated(h => {
    console.log(foo);  // this will throw "ReferenceError: foo is not defined"
    h.ctn();
 }));

我只需要使用
indexOf('{')
lastIndexOf('}')

constyourfunction=h=>{
控制台日志(h);
h、 ctn();
};
const fnText=yourFunction.toString();
const body=fnText.substring(fnText.indexOf('{')+1,fnText.lastIndexOf('}'));

控制台日志(主体)好的,这很有效,这并不难。 我们假设第一个和最后一个参数是函数体的轮廓

const isolated = function(fn){
  const str = fn.toString();
  const first = str.indexOf('{') + 1;
  const last = str.lastIndexOf('}');
  const body = str.substr(first, last-first);
  const paramNames = ['h'];
  return new Function(...paramNames.concat(body));
};

上面我们假设唯一的参数名为“h”,但您需要找到函数参数解析器。我以前使用过
require('function-arguments')

我编写了一个版本的
isolated()
,它处理任何非
bind
ed用户定义的函数表达式,并为作用域访问抛出自定义错误:

功能隔离(fn){
返回新函数(`
使用(新代理({}){
has(){return true;},
获取(目标、属性){
if(typeof property!=='string')返回目标[property];
抛出新的ReferenceError(属性+'从隔离范围访问');
},
集合(目标、属性){
抛出新的ReferenceError(属性+'从隔离范围访问');
}
}))返回${Function.prototype.toString.call(fn)}
`).call(新代理(函数(){},新代理({}{
get(){throw new ReferenceError('this accessed from insident scope');}
})));
}
//测试函数
[
()=>参数,//失败
()=>这个,//通过,没办法拦截
()=>this.foo,//失败
()=>this.foo='bar',//失败
()=>this(),//失败
()=>新建此,//失败
h=>h,//通过
h=>i,//失败
(a,b)=>b>a?b:a,//通过
].forEach(fn=>{
常数隔离=隔离(fn);
log(隔离.toString());
试一试{
隔离();
console.log('passed');
}捕获(错误){
log(`${error.name}:${error.message}`);
}

})
我很惊讶没有人问你为什么这么做。这有什么用途?为什么不在stringify操作后使用regex删除函数的内部体?@patrick这是为了测试。隔离函数意味着您有一个干净的作用域我知道隔离函数是什么,但您试图显式执行v8已经隐式执行的操作似乎很奇怪。@AlexanderMills在编写函数时,如果没有引用外部作用域中的任何变量,v8将自动将其标记为隔离并应用相关优化。您可以通过在Chrome上的函数中设置断点来确认这一点。如果您这样做并在断点处查看可用的作用域,您将无法从函数作用域内部访问外部作用域中的变量值,因为v8在JIT编译期间将函数标记为隔离的。是的..使用{}调用箭头函数很好…我想不出解析这些函数的好方法,可以吗?问题是如果省略了周围的字符,第一个“{”字符可能位于错误的位置。我认为正则表达式可以做到这一点。基本上检查=>后面的第一个字符是{还是其他什么。您也可以使用
const body=str.substring(first,last);
ahh substr与substring不同吗?
substr(indexStart,length)
vs.子字符串(indexStart,indexEnd)
nice我不知道有什么不同,gtkcool我可能会偷走它..将其放入NPM模块并编写一些测试,如果你不这样做,我将使其成为我的依赖项mind@AlexanderMills这是大量的免费工作。如果您不介意的话,我希望您只需将代码片段添加到内联注释中,并将其归功于此答案。当然没问题,我觉得你已经完成了大部分工作,如果你能在新答案之前提供更多信息,那就好了-我不了解它是如何在高水平上工作的,你仍然需要一个
函数,这与你在旧答案中需要它的原因相同。只是,你可以方便地将它包装在一个额外的作用域中,专门用于拦截作用域va变量引用使用
with(newproxy(…)
语句,并使用专用于引发任何类型用法的上下文调用函数构造函数。