Skip to content

Latest commit

 

History

History
44 lines (23 loc) · 2.34 KB

eval和with欺骗词法作用域影响性能.md

File metadata and controls

44 lines (23 loc) · 2.34 KB

欺骗词法作用域影响性能

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

JS代码执行过程的重要成员:

  • 引擎:

    从头到尾负责整个js程序的编译及执行过程

  • 编译器:

    引擎的好朋友之一,负责语法分析及代码生成等

  • 作用域:

    引擎的另一好朋友,负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当期执行的代码对这些标识符的访问权限

对变量的查询分类:

  • LHS查询:

    查找的目的是对变量进行赋值

  • RHS查询:

    查找的目的是获取变量的值

js引擎首先会在代码执行前对其进行编译,在这个过程中,像var a=2这样的声明会被分解成两个独立的步骤:

1.首先,var a在其作用域中声明变量,这会在最开始的阶段,也就是代码执行前进行;

2.接下来,a=2会查询(LHS查询)变量a并对其进行赋值;

欺骗词法作用域会导致性能下降:

eval和with会在运行时修改或创建新的作用域,以此来欺骗其他在书写时定义的词法作用域。

js引擎会在编译阶段进行数项的性能优化,其中有些优化项依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。 但如果引擎在代码中发现了eval和with,它只能简单地假设关于标识符位置的判断都是无效的,因为无法在词法分析阶段明确的知道eval会接收到什么代码,这些代码会如何对作用域进行修改,也无法知道传递给with用来创建新词法作用域的对象内容到底是什么,

最悲观的情况是如果出现了 eval(..) 或 with,所有的优化可能都是无意义的,因此最简 单的做法就是完全不做任何优化。

如果代码中大量使用 eval(..) 或 with,那么运行起来一定会变得非常慢。无论引擎多聪 明,试图将这些悲观情况的副作用限制在最小范围内,也无法避免如果没有这些优化,代 码会运行得更慢这个事实。