JS--Eval()

引言:

被誉为魔鬼的eval函数,今天看了一些文章和问答,总结了此博客,欢迎指正~

本文示例默认全部启用严格模式

Eval:执行代码字符串

内建函数eval允许执行一个代码字符串,代码字符串可能比较长,包含换行符、函数声明和变量等。
例如:

let code = 'alert("hello")'
eval(code) //hello

eval的结果是最后一条语句的结果

例如:

let value = eval('1+1')
alert(value) //2
let value = eval('let i = 0;++1')
alert(value) // 1

eval内的代码在当词法环境中执行,因此它可以访问外部变量:

let a = 1
function f() {
    let a = 2
    eval('alert(a)') //2
}
f()

同样可以改变外部变量

let x = 5
eval("x = 10")
alert(x)  // 运行结果是10,值被改变了

在严格模式下(use strict),eval有自己的词法环境,外部不能访问在eval中声明的函数和变量:

eval("let x= 5;funciton f() {}")

alert(typeof x)  // undifined

如果不启用严格模式,eval没有属于自己的词法环境,因此外部可以访问变量x和函数f。

使用eval

现代编程中,已经很少使用eval。人们经常说“eval是魔鬼”。
eval是一个危险的函数,它使用与调用者相同的权限执行代码。如果你用eval运行的字符串代码被恶意修改,最终可能会在网页/扩展程序的权限下,在用户计算机上运行恶意代码。更重要的是,第三方代码可以看到某一个eval被调用时的作用域,这也有可能导致一些不同方式攻击,相似的Function就不容易被攻击。

eval通常比其他替代方法更慢,因为它必须调用JS解释器,而许多其他结构则可被现代JS引擎进行优化。在旧的浏览器中如果你使用了eval,性能会下降10倍。在现代浏览器中有两种编译模式:fast path和slow path。fast path是编译那些稳定和可预测(stable and predictable)的代码。而明显的,eval不可预测,所以将会使用slow path ,所以会慢。

代码压缩工具(在把js投入生产环境前对齐进行压缩的工具)将局部变量重命名为更短的变量(例如a、b)以使代码体积更小。这个举动通常是安全的,但在使用了eval的情况下就不一样了,因为局部变量可能会被eval中的代码访问到,压缩工具不会对可能被从eval中访问的变量进行重命名,这样导致代码压缩率减低。在eval中使用外部局部变量会使代码维护变得更贱困难。

有两种方法可以规避此类问题:

如果 eval 中的代码没有使用外部变量,请以 window.eval(…) 的形式调用 eval:

通过这种方式,该代码便会在全局作用域内执行:

let x = 1;
{
  let x = 5;
  window.eval('alert(x)'); // 1(全局变量)
}

如果 eval 中的代码需要访问局部变量,我们可以使用 new Function 替代 eval,并将它们作为参数传递:

let f = new Function('a', 'alert(a)');

f(5); // 5

总结:

  • 调用 eval(code) 会运行代码字符串,并返回最后一条语句的结果。

  • 在现代 JavaScript 编程中,很少使用它,通常也不需要使用它。
    可以访问外部局部变量。这被认为是一个不好的编程习惯。

  • 要在全局作用域中 eval 代码,可以使用 window.eval(code) 进行替代。

  • 此外,如果你的代码需要从外部作用域获取数据,请使用 new Function,并将数据作为参数传递给函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值