你不知道的JavaScript【上】(Part1)第二章 词法作

2017-12-21  本文已影响2人  xunuo0x

词法作用域

作用域是一套规则:用来管理引擎如何在当前作用域以及嵌套子作用域中根据标识符名称进行变量查找。
作用域的两种工作模型:

  • 词法作用域
  • 动态作用域(Bash脚本、Perl中的一些模式)

1. 词法阶段

词法化对源代码中的字符进行检查,词法作用域是定义在词法阶段的作用域。
在查找时,作用域气泡的结构和相互之间的位置关系给引擎提供了足够的位置信息,引擎通过这些信息来查找标识符的位置。

遮蔽效应

作用域查找会在的一个匹配的标识符时停止。在多层的嵌套作用域中可以定义同名的标识符。

全局变量会自动成为全局对象(比如浏览器中的window 对象)的属性,因此可以不直接通过全局对象的词法名称,而是间接地通过对全局对象属性的引用来对其进行访问。

2. 欺骗词法

一般来说,词法作用域完全由写代码期间所声明的位置来定义,欺骗词法则是在运行时“修改”/“欺骗”词法作用域。

欺骗方式

with的说明:

function foo(obj) {
  with (obj) {
  a = 2;
  }
}
var o1 = {
a: 3
};
var o2 = {
b: 3
};
foo( o1 );
console.log( o1.a ); // 2
foo( o2 );
console.log( o2.a ); // undefined
console.log( a ); // 2——不好,a 被泄漏到全局作用域上了!

当o2传进去时,o2没有a属性,也就不会创建这个属性o2.a = undefined;就会通过LHS查找到全局作用域,并创建一个全局变量a

结论

导致的问题:性能的下降

JavaScript引擎在编译阶段会进行数项的性能优化,有些优化是依赖于能够根据代码的词法进行静态分析,预先确定所有变量和函数定义的位置,才能在执行时快速找到

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

3. 小结

词法作用域意味着作用域是由写代码时函数声明的位置来决定的,所以编译的词法分析阶段基本知道全部标识符在哪里,以及如何声明。

上一篇 下一篇

猜你喜欢

热点阅读