按名称模式搜索本地javascript变量

时间:2017-09-13 21:48:16

标签: javascript scope ecmascript-6

在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解决方案。任意代码已经被执行,因为用户提供的代码的执行是目的。

3 个答案:

答案 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 );

我自己没有尝试过这个文档表明它应该可以工作(或类似的东西):

http://esprima.readthedocs.io/en/latest/

答案 1 :(得分:0)

这里可能有用的一种方法是在全局范围而不是函数中进行求值,这可能会将函数放在窗口对象而不是局部范围内。

最简单的方法是将新标签写入文档并注入用户提供的代码。

答案 2 :(得分:0)

依赖变量名称是错误的方法。

eval是邪恶的。它可能不适用于CSP。考虑到代码应该在浏览器中运行,最大的问题是变量在缩小代码中没有预期的名称。它们是abc ...

为了维护他们的名字,他们应该是对象属性 - 因此它们将在对象上可用。

  

或者我必须采用重写(可能非常复杂的)代码的技术

这是重构,应该采取什么措施来避免代码产生异味并造成重大问题。