javascript - 评估以字符串形式给出的函数调用,该字符串使用 'require' 声明

标签 javascript

我需要使用一个只能在引号中访问的函数,因此它是一个字符串。

假设函数名为“m”。该函数是一个 NPM 包。我使用“require”将其导入到我的项目中。

假设字符串是另一个函数给我的。因此我没有机会简单地删除引号。

const m = require('mithril')
let vnode = "m('p', 'text')" // I need this string as a function

我通过网络进行了搜索,得出了两个答案。使用 eval() 或 Function()。

现在,eval 可以正常工作了。然而,我发现很多人一直在说 eval() 是邪恶的、缓慢的,即使我认为是时候使用它也应该避免。我正在尝试在 github 页面上构建一个单页应用程序 - 仅供引用 - 也许 eval() 在这种情况下可以使用。

Function() 表现得很奇怪。当我执行 Function("m('p', 'text')") 时,它返回这个(作为字符串):

function anonymous( ) { m("p", "text" ) }

...当我调用它时 Function("m('p', 'text')")(),它返回一个错误,说:

ReferenceError: m is not defined

我试图在 Function() 调用中再次require 模块 mithril ,但是这次它给出了一个错误,指出 require 未定义。我认为这是因为 Function 来自不同的环境而不是来自 Nodejs。

我只是期待 eval 函数的行为,而不用担心被黑客攻击。

有什么想法吗?

编辑(进一步解释):

我注意到我在 X/Y 问题中问 Y。这是我的问题的 X。

我正在使用 Mithril JS 将单页应用程序部署到 github 页面. ( my repo )

我需要渲染数学表达式,其中 KaTeX进来了。

KaTeX 自带 a simple API , renderToString() 函数返回一个 HTML 元素,该元素呈现为呈现良好的数学表达式。

另一方面,Mithril JS 渲染了 VNodes,一种描述 HTML 标签的特殊功能。示例:

<div class="cont">
    <p>
        Text
    </p>
</div>

... 当转换为 vnodes ...

m('div', {class:'cont'}, [
    m('p', 'Text')
])

现在,为了 Mithril 能够正确查看 KaTeX 的 HTML 输出,html 标签应该被翻译成 Vnodes。我找到了一个 converter here

我将转换器的代码添加到我的项目中并将其作为函数导入。我在这里面临的问题是转换器完美地将 HTML 结构转换为 VNode,但它以字符串形式返回它们,并用引号引起来...

我能想到的解决方案:

  • 将另一个包添加到我的项目中,允许 Mithril 使用 JSX 语法,其中 JS 可以在 HTML 标记中穿插编写。这是我最后的选择,但我个人不喜欢 JSX 语法,因为它只是一种权衡。
  • 使用 eval() 函数,它完美地完成了我想要的,但安全问题是众所周知的。

还有其他想法吗?

最佳答案

将类似 eval 的字符串转换为参数数组,然后使用这些参数调用 m 可能会更优雅。例如,如果参数始终是用 's 分隔的字符串:

// const m = require('mithril')
// for demonstration purposes:
const m = (...args) => console.log('called with ' + args.join(','));

const vnode = "m('p', 'text')"
let match;
const pattern = /'([^']+)'/g;
const args = [];
while (match = pattern.exec(vnode)) {
  args.push(match[1]);
}
m.apply(undefined, args);

如果函数名称也可以变化,则使用带有 m 键的对象而不是独立变量:

// const m = require('mithril')
// for demonstration purposes:
const fns = {
  m: (...args) => console.log('called with ' + args.join(','))
};

const vnode = "m('p', 'text')";
const fnName = vnode.match(/^[^(]+/)[0];
let match;
const pattern = /'([^']+)'/g;
const args = [];
while (match = pattern.exec(vnode)) {
  args.push(match[1]);
}
fns[fnName].apply(undefined, args);

关于javascript - 评估以字符串形式给出的函数调用,该字符串使用 'require' 声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54058166/

相关文章:

javascript - SimpleHTTPServer 错误 404 - "GET/d3/d3.v3.js HTTP/1.1"404

javascript - react Hook useEffect 在按钮单击时获取数据( typescript )

javascript - cookie问题,关闭浏览器后cookie丢失

javascript - 如何显示错误消息以便 jquery 验证引擎?

javascript - 如何使用 javascript 获取小数点后两位而不四舍五入的数字?

javascript - 在nodejs中为oracledb提交后释放连接的正确方法是什么

javascript - 如何获取OpenUI5绑定(bind)信息

javascript - 如何使用CSS动态修复顶部

javascript - 在同一个 InfoWindow() 中显示具有相同坐标的绘图点

javascript - 无法使用 React.js refs 滚动到 div 的底部