Phi Asked: 2020-08-29 15:21:17 +0800 CST 2020-08-29 15:21:17 +0800 CST 2020-08-29 15:21:17 +0800 CST 什么时候需要使用 Javascript 的 eval() 函数? 772 理解了函数的使用eval(),理解为将stringa 求值为 Javascript 表达式,但不推荐使用方向。 使用该函数的一个示例是以下代码段: var refreshTime = 'setTimeout(function(){ console.log("Writing somehing every second!"); }, 1000);'; eval(refreshTime) 是否有任何可能的情况,其中使用Eval()是一种选择,或者在你的情况下,是必要的和/或必需的? 同样,一个让我不清楚函数范围的问题是timeout它只执行一次,而不是它应该每秒执行一次。 javascript 4 Answers Voted Best Answer user22721 2020-08-30T07:51:03+08:002020-08-30T07:51:03+08:00 一个非常有趣的问题,我会冒险回答它,我希望能做到。 对于这个问题: 什么时候需要使用 Javascript 的 eval() 函数? 从来没有,在浏览器不支持我们今天拥有的所有功能的日子里,也许我们可以找到一个我们可能需要它的案例。 例如,假设我们有一个 JSON 字符串,我们需要将其转换为一个值以供使用: let userString = "{\"name\":\"Carlos\", \"username\":\"KacosPro\"}"; let user = eval('('+userString+')'); console.log(user); 但是今天我们可以说,超过 90% 的浏览器都支持该语法JSON.parse() let userString = "{\"name\":\"Carlos\", \"username\":\"KacosPro\"}"; let user = JSON.parse(userString); console.log(user); 但是如果我的 JSON 字符串以另一种格式出现怎么办? 假设我们得到一个具有这种形式的字符串{name: "Carlos", username: "KacosPro"} let userString = "{name: 'Carlos', username: 'KacosPro'}"; let user = eval('('+userString+')'); console.log(user); 我们找到了它的用途!是的,但是 JSON 的格式不正确,因此它不是有效的 JSON,规范清楚地指出,在 JSON 中,字符串是零个或多个 Unicode 字符的序列,用引号括起来转义带有 源反斜杠的双打 我们可以找到的另一个用途是动态调用函数,例如 function hello() { console.log('Hello'); } function goodBye() { console.log('Bye'); } const call = 'hello()'; eval(call); 但是我们仍然可以找到另一种方法来做到这一点 function hello() { console.log('Hello'); } function goodBye() { console.log('Bye'); } const call = 'hello'; this[call](); 综上所述 更不用说它是一个潜在的不安全函数,因为如果不小心使用它,有人可以在我们的 scipts 中执行代码。 对于可以找到的每一种用途,我们都有一种更有效的方法来避免它。 是否有任何可能的情况,其中使用eval()是一种选择,或者在你的情况下,是必要的和/或必需的? 是的,可能有几种情况,例如创建者JSON.parse()使用它但在对其进行清理并检查它是否是有效的 JSON 字符串之后。我们可以看到它说的是什么: 在第三阶段,我们使用 eval 函数将文本编译成 JavaScript 结构。 或西班牙语(如果您发现翻译有问题,请随时编辑): 第三阶段我们使用 eval 函数将文本编译成 JavaScript 结构 我们可以在这里看到它的用途 最后为你的疑惑 同理,一个没有让我明确函数作用域的问题是这个超时时间只执行一次 setTimeout()超时后执行函数,并且只执行一次 console.log(new Date()); setTimeout(() => {console.log(new Date())}, 1000) 如果您需要不时执行它,则应使用该函数setInterval(),这是一个实际示例: setInterval(function(){ console.log("Writing something every second!"); }, 1000); 或者,如果您希望它在某个操作之后启动,我们可以将其封装在一个函数中 function refreshTime() { setInterval(() => {console.log("Writing something every second!")}, 1000); } <button onclick="refreshTime()">Click me!</button> Bryro 2020-08-29T17:27:48+08:002020-08-29T17:27:48+08:00 eval()函数被广泛用于混淆代码并降低其可读性,例如在付费库中! 它有许多实用程序示例:webscraping!当您对网站提出请求时,您会以纯文本形式获得它。你可以做: let response = request.split("<script>")[1].split("</script>")[0] eval(response); //obtendrías el script para ejecutar y no solo como texto plano! 您还可以看到一个在线混淆器。 function a(){alert("hello world");}a(); 并将其混淆为: eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--){d[c]=k[c]||c}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1 0(){2("3 4")}0();',5,5,'a|function|alert|hello|world'.split('|'),0,{})) Pablo Lozano 2022-07-22T08:40:17+08:002022-07-22T08:40:17+08:00 我将提供一个更新的答案,并提供一个不太糟糕的选项: 何时使用评估? 从来没有,这是危险的,真的没有理由这样做。使用此函数执行的代码具有全局访问权限。 但是我已经知道要执行的代码,它是我从自己的站点下载的 JS。 所以没有理由使用eval,您可以动态加载代码并更有效地运行它。 如果无论如何,我需要执行我收到的文本代码怎么办? 该函数eval()具有全局访问权限,这既危险又昂贵(要执行的代码非常慢)。更好的解决方案是使用具有本地“范围”的代码创建一个函数: 馊主意:eval("(" + obj + ")"); 一个更好的主意:Function('"use strict";return (' + obj + ')')(); 在 Javascript 中,函数是“一等公民”。也就是说,它们是可以创建并具有特定属性的通用对象。调用此函数的成本稍微低一些,而且更安全,因为访问受限于函数内部。它更便宜的原因正是因为 eval 如果给定标识符存在,则强制编译器查看更高的范围,而 Function 没有,它仅适用于本地范围和对象window: (() => { const evalCode=`"use strict"; a= 11;` const functionCode=`"use strict"; a= 22;` let a = 0; function callEval(code) { eval(code); } function createFunction(code) { return new Function(code); } console.log(a); callEval(evalCode); console.log(a); const f = new createFunction(functionCode); try { f() } catch(e) { console.log("llamada a f falla:", e.message); } console.log(a); })() Emeeus 2022-07-22T06:33:23+08:002022-07-22T06:33:23+08:00 这很有趣,因为从理论上证明其使用的唯一用途是当要执行的代码以前不知道时,可能是因为它是动态生成的,例如在服务器上。假设否则我们将代码作为代码而不是字符串。 在这种情况下,我的意思是“理论上它可以证明它的使用是合理的”,因为它不能以任何其他方式完成,而不是使用eval(). 在我看来,这种情况意味着 100% 的情况下存在设计缺陷。也就是说,从这个意义上说,它永远不会被证明是正当的。 这个事实(要执行的代码以前不知道)正是使其潜在“危险”的原因,特别“危险”的事实是 XSS 攻击的可能性(跨站点脚本,我推荐OWASP以获得详细信息)。 也就是说,在理论上证明它不能以其他方式完成的唯一事实,正是使它变得危险的特性。 但是动态代码执行并不是唯一的用途,其中一种用途只是抽象代码或故意混淆它,正如@Bryro 提到的那样。换句话说,它是可以以另一种方式完成的代码。 例如,这是使用以下方法获取数组平均值的一种方法eval(): const ar = [11,2,100,56,78,90,22]; const promedio = eval(ar.join('+'))/ar.length; console.log(promedio); 它是可以清楚地完成而不需要的代码,eval()但它的使用使它非常简短和简洁。至少在大多数情况下,代码可以用另一种方式来完成,也就是说理论上没有必要eval(),所说的代码根本没有危险。这就是问题的悖论。一般来说,当它不是“必要的”时,它会是“安全的”。 最后,我澄清一下,我使用“至少在大多数情况下”或“一般情况下”这样的表达方式,因为并非所有可能性都是已知的,如果我们查看 OWASP,就会定期添加漏洞。发生的情况eval()是它可能是 XSS 攻击的载体,即使在我们还不知道的情况下也是如此,这就是为什么它坚持根本不使用它的原因。 我故意省略了一些我认为有点不寻常的非常具体的情况,例如 JavaScript sanboxing,以及eval()在其他函数中的隐式使用。沙盒将是存在于 StackOverflow 上的 JavaScript 代码执行器的情况,在 jsfiddle 或类似的地方,使用eval()或构造函数Function是强制性的。隐式使用将在诸如 之类的函数中.innerHTML,其中代码实际上由其他函数作为字符串执行。
一个非常有趣的问题,我会冒险回答它,我希望能做到。
对于这个问题:
从来没有,在浏览器不支持我们今天拥有的所有功能的日子里,也许我们可以找到一个我们可能需要它的案例。
例如,假设我们有一个 JSON 字符串,我们需要将其转换为一个值以供使用:
但是今天我们可以说,超过 90% 的浏览器都支持该语法
JSON.parse()
但是如果我的 JSON 字符串以另一种格式出现怎么办?
假设我们得到一个具有这种形式的字符串
{name: "Carlos", username: "KacosPro"}
我们找到了它的用途!是的,但是 JSON 的格式不正确,因此它不是有效的 JSON,规范清楚地指出,在 JSON 中,字符串是零个或多个 Unicode 字符的序列,用引号括起来转义带有 源反斜杠的双打
我们可以找到的另一个用途是动态调用函数,例如
但是我们仍然可以找到另一种方法来做到这一点
综上所述
更不用说它是一个潜在的不安全函数,因为如果不小心使用它,有人可以在我们的 scipts 中执行代码。
对于可以找到的每一种用途,我们都有一种更有效的方法来避免它。
是的,可能有几种情况,例如创建者
JSON.parse()
使用它但在对其进行清理并检查它是否是有效的 JSON 字符串之后。我们可以看到它说的是什么:或西班牙语(如果您发现翻译有问题,请随时编辑):
我们可以在这里看到它的用途
最后为你的疑惑
setTimeout()
超时后执行函数,并且只执行一次如果您需要不时执行它,则应使用该函数
setInterval()
,这是一个实际示例:或者,如果您希望它在某个操作之后启动,我们可以将其封装在一个函数中
eval()函数被广泛用于混淆代码并降低其可读性,例如在付费库中!
它有许多实用程序示例:webscraping!当您对网站提出请求时,您会以纯文本形式获得它。你可以做:
您还可以看到一个在线混淆器。
并将其混淆为:
我将提供一个更新的答案,并提供一个不太糟糕的选项:
何时使用评估?
从来没有,这是危险的,真的没有理由这样做。使用此函数执行的代码具有全局访问权限。
但是我已经知道要执行的代码,它是我从自己的站点下载的 JS。
所以没有理由使用eval,您可以动态加载代码并更有效地运行它。
如果无论如何,我需要执行我收到的文本代码怎么办?
该函数
eval()
具有全局访问权限,这既危险又昂贵(要执行的代码非常慢)。更好的解决方案是使用具有本地“范围”的代码创建一个函数:馊主意:
eval("(" + obj + ")");
一个更好的主意:
Function('"use strict";return (' + obj + ')')();
在 Javascript 中,函数是“一等公民”。也就是说,它们是可以创建并具有特定属性的通用对象。调用此函数的成本稍微低一些,而且更安全,因为访问受限于函数内部。它更便宜的原因正是因为 eval 如果给定标识符存在,则强制编译器查看更高的范围,而 Function 没有,它仅适用于本地范围和对象
window
:这很有趣,因为从理论上证明其使用的唯一用途是当要执行的代码以前不知道时,可能是因为它是动态生成的,例如在服务器上。假设否则我们将代码作为代码而不是字符串。
在这种情况下,我的意思是“理论上它可以证明它的使用是合理的”,因为它不能以任何其他方式完成,而不是使用
eval()
. 在我看来,这种情况意味着 100% 的情况下存在设计缺陷。也就是说,从这个意义上说,它永远不会被证明是正当的。这个事实(要执行的代码以前不知道)正是使其潜在“危险”的原因,特别“危险”的事实是 XSS 攻击的可能性(跨站点脚本,我推荐OWASP以获得详细信息)。
也就是说,在理论上证明它不能以其他方式完成的唯一事实,正是使它变得危险的特性。
但是动态代码执行并不是唯一的用途,其中一种用途只是抽象代码或故意混淆它,正如@Bryro 提到的那样。换句话说,它是可以以另一种方式完成的代码。
例如,这是使用以下方法获取数组平均值的一种方法
eval()
:它是可以清楚地完成而不需要的代码,
eval()
但它的使用使它非常简短和简洁。至少在大多数情况下,代码可以用另一种方式来完成,也就是说理论上没有必要eval()
,所说的代码根本没有危险。这就是问题的悖论。一般来说,当它不是“必要的”时,它会是“安全的”。最后,我澄清一下,我使用“至少在大多数情况下”或“一般情况下”这样的表达方式,因为并非所有可能性都是已知的,如果我们查看 OWASP,就会定期添加漏洞。发生的情况
eval()
是它可能是 XSS 攻击的载体,即使在我们还不知道的情况下也是如此,这就是为什么它坚持根本不使用它的原因。我故意省略了一些我认为有点不寻常的非常具体的情况,例如 JavaScript sanboxing,以及
eval()
在其他函数中的隐式使用。沙盒将是存在于 StackOverflow 上的 JavaScript 代码执行器的情况,在 jsfiddle 或类似的地方,使用eval()
或构造函数Function
是强制性的。隐式使用将在诸如 之类的函数中.innerHTML
,其中代码实际上由其他函数作为字符串执行。