本文介绍了创建辅助函数以在隔离范围内运行函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码有效:

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

  it.cb(new Function(
    'h', [
      'console.log(h)',
      'h.ctn()'
    ]
    .join(';')
  ));

这两个测试用例基本相同。但是构造一个像这样的数组的字符串是很麻烦的,你不能得到静态分析。所以我想做的事情是这样的:

these two test cases are basically identical. But constructing a string with array like that is cumbersome, and you can't get static analysis. So what I was thinking of doing was something like this:

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

其中Isolated是一个辅助函数,类似于:

where isolated is a helper function that looks something like:

const isolated = function(fn){
   const str = fn.toString();
   const paramNames = getParamNames(str);
   return new Function(...paramNames.concat(str));
};

最大的问题是 Function.prototype.toString()为您提供全部功能。有没有人知道从函数的字符串表示中获取函数体的好方法?

the biggest problem is that Function.prototype.toString() gives you the whole function. Does anyone know of a good way to just get the function body from the string representation of the function?

更新:PRoberts问的目的是什么,目的是什么简单地说:

Update: PRoberts was asking what the purpose of this is, the purpose is simply:

 const foo = 3;

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


推荐答案

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

I wrote a version of isolated() that handles any non-binded user-defined function expression and throws custom errors for scoped accesses:

function isolated (fn) {
  return new Function(`
    with (new Proxy({}, {
      has () { return true; },
      get (target, property) {
        if (typeof property !== 'string') return target[property];
        throw new ReferenceError(property + ' accessed from isolated scope');
      },
      set (target, property) {
        throw new ReferenceError(property + ' accessed from isolated scope');
      }
    })) return ${Function.prototype.toString.call(fn)}
  `).call(new Proxy(function () {}, new Proxy({}, {
    get() { throw new ReferenceError('this accessed from isolated scope'); }
  })));
}

// test functions
[
  () => arguments, // fail
  () => this, // pass, no way to intercept this
  () => this.foo, // fail
  () => this.foo = 'bar', // fail
  () => this(), // fail
  () => new this, // fail
  h => h, // pass
  h => i, // fail
  (a, b) => b > a ? b : a, // pass
].forEach(fn => {
  const isolate = isolated(fn);
  console.log(isolate.toString());

  try {
    isolate();
    console.log('passed');
  } catch (error) {
    console.log(`${error.name}: ${error.message}`);
  }
})

这种实现稍微简单一些,因此比尝试解析用户定义函数的参数和主体更不容易出错。

This implementation is somewhat simpler, and therefore much less error-prone than attempting to parse the parameters and body of a user-defined function.

with 语句是一种相对简单的方法,用于捕获强制隔离函数中的任何作用域引用并抛出的ReferenceError 。它通过将一个代理中间件插入到作用域中,并使用一个get陷阱来拦截已访问的作用域变量名称。

The with statement is a relatively simplistic means of catching any scoped references within the forcibly isolated function and throwing a ReferenceError. It does so by inserting a Proxy intermediate into the scope with a get trap that intercepts the scoped variable name that was accessed.

作为函数上下文传递的代理是唯一有点难以实现的部分,也是不完整的。这是必要的,因为作为 with 语句的范围提供的代理不会拦截对<$ c $的访问c>这个关键字,所以上下文也必须明确包装,以拦截并抛出孤立箭头函数内的 this 的任何间接用法。

The Proxy that is passed as the context of the function was the only part that was a bit tricky to implement, and also incomplete. It was necessary because the Proxy provided as the scope to the with statement does not intercept accesses to the this keyword, so the context must also be wrapped explicitly in order to intercept and throw on any indirect usage of this inside an isolated arrow function.

这篇关于创建辅助函数以在隔离范围内运行函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 12:53