为什么不建议使用eval和with?

作者: 悟C | 来源:发表于2018-07-01 14:05 被阅读29次
假装被面试

面试官:为什么不建议使用eval和with?

因为影响性能、减低代码的安全性、代码更加难于阅读。

那为什么会影响性能?、为何会减低安全性?、怎么就让代码更加难于阅读?

这个些问题主要是考察Js开发人对词法作用域的理解,如果你和我一样一脸蒙蔽那就跟着我一起来看看这其中的"奥秘"吧!

先了解一下什么是词法作用域

简单地来说,词法作用域就是定义在词法阶段的作用域。词法作用域是由你在写代码时将变量和块作用域写在哪了来决定的,因此当词法分析器处理代码时会保存作用域不变(大部分情况下是这样)

下面用一张图帮助理解作用域:


来自《你不知道的JavaScript上卷》

(1)、包含着整个全局作用域,其中只有一个标识符:foo
(2)、包含着foo所创建的作用域,其中有三个标识符: a、b、 bar
(3)、包含着bar所创建的作用域,其中只有一个标识符:c

从上面那张图片可以看到,作用域是逐级嵌套的。在执行console.log(a, b, c)时,引擎会从最内部的作用域(3)开始查找,如果没有找到,就逐层往外找。⚠️作用域查找会在找到第一个匹配的标识符时停止


下面回归正题,为什么会影响性能?

这里就要提到“欺骗词法(代码在运行的时候"修改"词法作用域)”这个词, JavaScript引擎在编译阶段有一些性能上的优化是依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速的找到标识符。

但如果引擎在代码中发现了eval或with,它只能简单地假设关于标识符位置但判断都是无效的,因为无法在词法分析阶段明确的知道eval会接收到什么代码,这些代码是如何对作用域进行修改,因此最简单的做法就是完全不做任何优化。如果代码中大量使用eval和with,导致引擎没有对这些进行优化。那么代码运行起来一定会变得更慢。

代码安全问题

我们都知道eval接收一个字符串,然后解释为一段可执行的代码,在传递进来的字符为不可预知的情况,这是多么危险的行为。在JavaScript中有类似功能,还有: setTimeoutsetIntervalnew Function,我们应该尽量避免这样使用它们。

说到with,它会在你不知的情况下把一些内部作用域声明的函数或者变量泄露到其他作用域,例如泄露到全局:

function a() {
 console.log('hello')
}

function foo(obj) {
 with(obj) {
   a = function() {
     console.log("hi")
   }
 }
}

var obj = {
 b: 3
}
a();   // hello
foo(obj)
console.log(obj.a)   // undefined
a();                        // hi

在obj创建了作用域没有找到a,然后在foo()作用域找,也没有找到、最后在全局作用域中找到了,然后就把它给改了。

代码更加难于阅读

这个就不难说明,如果传递给它们的参数都是不可预知的变量。那肯定难于阅读,因为你根本不知道代码下一步运行会不会改变这个变量。

总结

with和eval的本意是好,但它们阻断了变量名的词法作用域绑定,导致的副作用远远大于它的使用价值,所以我们应该在开发中避免使用它们。


参考资料

《你不知道的Javascript》上卷

相关文章

  • 为什么不建议使用eval和with?

    面试官:为什么不建议使用eval和with? 因为影响性能、减低代码的安全性、代码更加难于阅读。 那为什么会影响性...

  • with、eval、strict严格模式

    一、with语句,不推荐使用 with语句可以形成自己的作用域,不建议使用 二、eval函数,不推荐使用 一个特殊...

  • 9.eval函数

    eval是一个特殊的全局函数,它可以将传入的字符串当做JavaScript代码来运行。 不建议在开发中使用eval...

  • 内置函数

    内建函数: 其他相关 不建议使用字符串类型代码的执行 eval,exec,complieeval: 执行字符串类...

  • 面经之js

    1.eval是做什么的?为什么尽量避免使用eval? Javascript全局对象,eval()函数可以计算机某个...

  • ajax请求JSON数据并解析

    通常,从后台拿到的时JSON字符串。所以用JSON.parse来转为JSON对象,不建议使用eval()函数,因为...

  • day13-01 Python的内置函数

    内置函数 python一共提供了68个内置函数 不太常用: eval:剥去函数的外衣运算里面的代码 不建议使用,因...

  • 为什么不建议使用@import引入css

    为什么不建议使用@import引入css 不建议使用@import主要有以下两点原因: 原因一、使用@import...

  • 二级Python小知识点---eval函数的功能

    eval函数的功能: eval函数的参数必须是字符串。所以经常和input联合使用。 eval函数的功能,通俗的说...

  • JS中eval()解析和为什么不要使用eval

    eval翻译:是evaluate,评估,评价的意思。eval的重点在于eval函数名赋值给变量之后,它的作用域可能...

网友评论

    本文标题:为什么不建议使用eval和with?

    本文链接:https://www.haomeiwen.com/subject/xbdcuftx.html