词法作用域(词法作用域和函数作用域)
词法作用域
作用域就是一套规则,用来管理引擎如何在当前作用域以及嵌套的子作用域根据标识符名称进行变量查找。作用域分为词法作用域和动态作用域。
大部分标准语言编译器的第一个工作阶段叫做词法化,词法化的过程会对源代码中的字符进行检查,词法作用域就是定义在词法阶段的作用域。 词法作用域是由你写代码时将变量和块作用域写在哪里决定的,因此词法分析器处理代码时会保持作用域不变(绝大多数情况下,不过我们可以用eval等方法进行欺骗词法作用域)。
function foo(a) { var b = a * 2; function bar (c) { console.log(a, b, c); } bar(b * 3); } foo(2); 复制代码
这串代码中有3个嵌套作用域: 全局作用域,foo作用域和bar作用域。这些作用域都是严格包含的,没有任何函数作用域可以同时出现在两个外部作用域中。作用域查找会在找到第一个匹配的标识符时停止。
全局变量会自动成为全局对象的属性,在浏览器中就是window对象,因此可以不直接通过全局对象的词法名称,而是间接地通过对全局对象属性的引用来对其进行访问: window.a
。通过这样可以访问那些被同名变量所遮蔽的全局变量。
欺骗词法
eval()
函数可以接受一个字符串作为参数,并将其中内容当作书写时就存在于程序中这个位置的代码。也就是说我们可以在代码中生成代码并运行,就好像代码是原先就在这个位置一样。
在执行evel()之后的代码时,引擎并不知道前面的代码是以动态形式插入,并对词法作用域进行修改的。引擎会按照往常进行词法作用域查找。
function foo(str, a) { eval(str); console.log(a, b); } foo("var b = 2;", 1); //1, 2 复制代码
eval()的性能问题
JavaScript引擎会在编译阶段进行数项性能优化,其中一些优化是基于能够对代码中的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行中快速找到标识符。如果引擎在代码中发现了eval
,它只能简单的假设关于标识符的位置判断都是无效的,因为不能确定eval
中到底接收了什么代码,这些代码会对作用域进行什么修改。
因此最简单的方法就是完全不做任何优化,如果代码中大量使用的话,那运行起来会变得慢。
伪原创工具 SEO网站优化 https://www.237it.com/
作者:墨安
链接:https://juejin.cn/post/7036011221862219812