我写了一个版本,isolated()可以处理任何非bind用户定义的函数表达式,并为范围访问抛出自定义错误:
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}`); }})与尝试解析用户定义函数的参数和主体相比,此实现稍微简单一些,因此不容易出错。
该with语句是一种相对简单的方法,用于在强制隔离的函数中捕获所有作用域的引用并抛出
ReferenceError。它通过
Proxy使用一个
get陷阱将一个中间变量插入到作用域中来实现,该陷阱会拦截所访问的作用域变量名。
在
Proxy作为函数的背景是,这是一个有点棘手来实现,也残缺的唯一部分传递。这是必要的,因为
Proxy提供给
with语句的作用域不会拦截对
this关键字的访问,因此还必须显式包装上下文,以拦截并间接使用
this隔离的箭头函数内部的任何间接用法。



