【问题标题】:Why new Function not work as eval?为什么 new Function 不能作为 eval 工作?
【发布时间】:2018-08-28 14:09:05
【问题描述】:

例如,我有一个代码(带有新功能),它将打开一个警报窗口

   new Function`alert(1)`; // Works OK

eval上的代码相同

   eval('alert(1)'); // Works OK

但是如果我使用计算:

 new Function`2+2`; // not works, shows {}

Eval 工作正常:

   eval('2+2'); // Works OK , will be 4 

问题:

为什么是代码:

 new Function`2+2`; 

不工作?

【问题讨论】:

  • 你的意思是new Function("2+2"); 带括号吗?如果你不使用括号,你实际上并没有调用任何东西。
  • @zero298 错误!这是 es6/7 中的正确代码。使用 ES6/7,你可以调用一个函数,传递一个模板文字。
  • @Megajin 你能显示文档吗?我从未见过使用过的,我在 MDN 文档中找不到它:Template literals
  • @zero298 相关部分是“标记模板”。

标签: javascript function eval calculation ecmascript-2016


【解决方案1】:

最初的问题是:

为什么是代码:new Function2+2;不工作?

为了简单地解释这一点,您必须查看 JavaScript Function 构造函数将接受哪些参数:MDN Function 如您所见,所需的输入是字符串:

const sum = new Function('a', 'b', 'return a + b');

console.log(sum(2, 6));
// expected output: 8

如果你这样做:

new Function`2+2`;

您将简单地创建一个匿名实例,而无需使用任何值或返回值。这就是为什么输出会是anonymous {}

我认为不可能使用带有模板字符串的函数调用 计算,它只适用于单引号或双引号

我可以证明它会起作用 - 有不同的方法可以解决这个问题:

new Function('return arguments[1]')`${2+2}`; // outputs 4
new Function`return Object.entries(arguments)[0]`(2+2); // outputs ['0',4]

我想你现在可以理解如何使用Function 构造函数和tagged templates。重要的部分是使用 arguments 对象并访问您想要的返回值。

eval 的旧答案:

const myFunc = evalStr => console.log(eval(evalStr[0]));
myFunc`2+2`;

更多信息:

【讨论】:

  • 感谢您的回答,但我想使用没有 eval 的新功能
  • 我确实在我的答案中添加了更多细节,现在应该很清楚 =)。
  • new Function('return arguments[1]')${2+2};这将立即执行(当您发送参数时),它将被解释为 new Function('return arguments[1]')${4} ,这没有意义; 2+2 应该作为字符串发送而不是作为数字 4
  • 你可以做 '${2+2}''2+2' 并在参数中解释它。一切皆有可能,我只是想向您展示您“可以”使用模板文字。顺便说一下,这个new Function('return 2+2') 将被解释为function() {return 2+2;},所以它和我展示的一样,但带有模板文字。
【解决方案2】:

我认为不可能使用带有模板字符串的函数调用进行计算,它只能使用单引号或双引号

const result = new Function('return 2+2')();

console.log(result); // 4

【讨论】:

  • 我可以证明你错了,标签模板是可能的。看我的回答。
  • @Megajin ,感谢您的回答,但我想使用没有 eval 的新功能
  • 好的,我可以证明有一种方法。给我几分钟,我会修改我的答案。
【解决方案3】:

当你在 JavaScript 中使用反引号时,它被称为模板文字。详情可以看this document

基本上,您在反引号中传递给函数的字符串作为参数传递给您尚未定义函数的函数。当使用带有函数的反引号时,它被称为标记模板文字。您需要首先定义函数(如何对传入的字符串进行数学运算)。在您的情况下,您想使用 eval,因此您的标签应如下所示:

const myTaggedTemplateLiteral = (evalStrings) => eval(evalStrings[0]);
myTaggedTemplateLiteral`2+2` // 4

【讨论】:

  • 感谢您的回答,但我想使用没有 eval 的新功能
【解决方案4】:

你应该在计算之前返回:

var a = new Function("return 2+2");

如果你想让它动态化,只需添加参数

var a = new Function("x", "y", "return x+y");

【讨论】:

  • 请删除这个答案!此代码是从我的评论中复制粘贴的
  • 仅代码答案是不好的做法,您至少应该解释一下您在做什么。 How do I write a good answer?
猜你喜欢
  • 2021-10-13
  • 2021-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 2013-03-18
相关资源
最近更新 更多