在Javascript中,局部变量不会存在于我所知道的任何对象上。也就是说,
function foo() {
const x = 2;
self.x; // undefined
this.x; // undefined
window.x; // undefined
x; // 2, obviously
eval('x'); // 2
}
最后一个选项eval('x')
表明可以通过名称引用这些变量。我正在寻求扩展它并使用名称 pattern :
function foo() {
// Code not under my direct control
function foobar_abc() {}
function other_functions() {}
// Code under my control
const matchingFunction = // find the function with name matching 'foobar_*'
}
如果它存在于一个物体上,我会使用类似myObject[Object.keys(myObject).find((key) => key.startsWith('foobar_'))]
的东西。如果它在全球范围内,myObject
将为window
,一切正常。
eval
能够按名称访问变量这一事实意味着该值在某处可用。有没有办法找到这个变量?或者我必须采用重写(可能非常复杂)代码的技术,这些代码不在我的直接控制之下?
我的目标是现代浏览器,在这个用例中,我不介意使用eval
或类似的hacky解决方案。任意代码已经被执行,因为用户提供的代码的执行是目的。
答案 0 :(得分:1)
另一种选择是使用代码解析来使用javascript AST(抽象语法树)库推导出函数名称。 “esprima”套餐可能是个好看的地方:
https://www.npmjs.com/package/esprima
所以你可以做到
import esprima from 'esprima'
const userCodeStructure = esprima.parseScript( userProvidedJavascriptString );
const allTopLevelFunctionDeclarations = userCodeStructure.body.filter( declaration => declaration.type === "FunctionDeclaration" );
const allTopLevelFunctionNames = allTopLevelFunctionDeclarations.map( d => d.id );
我自己没有尝试过这个文档表明它应该可以工作(或类似的东西):
答案 1 :(得分:0)
这里可能有用的一种方法是在全局范围而不是函数中进行求值,这可能会将函数放在窗口对象而不是局部范围内。
最简单的方法是将新标签写入文档并注入用户提供的代码。
答案 2 :(得分:0)
依赖变量名称是错误的方法。
eval
是邪恶的。它可能不适用于CSP。考虑到代码应该在浏览器中运行,最大的问题是变量在缩小代码中没有预期的名称。它们是a
,b
,c
...
为了维护他们的名字,他们应该是对象属性 - 因此它们将在对象上可用。
或者我必须采用重写(可能非常复杂的)代码的技术
这是重构,应该采取什么措施来避免代码产生异味并造成重大问题。