作用域和闭包
作用域和闭包
LHS和RHS
LHS查询是试图找到变量的容器本身,然后对其赋值
RHS查询是简单地查找某个变量的值
在变量还没有声明(在任何作用域中都无法找到该变量)的情况下:
- RHS查询所有嵌套的作用域中都找不到对应的变量,则会抛出ReferenceError
- LHS查询,如果在最顶层(全局作用域)中都无法找到该变量,则会在全局作用域中创建一个具有该名称的变量(程序运行在非严格模式下);如果是在严格模式下,则会抛出和RHS类似的异常
作用域查找
作用域查找会在找到第一个匹配的标识符时停止,同时始终从运行时所处的最内部作用域开始,逐级向外或向上进行,直到遇到第一个匹配的标识符
词法作用域查找只会查找一级标识符,如果代码中引用了foo.bar.baz,词法作用域只会试图查找foo标识符,找到这个变量后,对象属性访问规则会接管对bar和baz属性的访问
欺骗词法
JavaScript提供了两种机制来实现:运行时修改词法作用域
eval
接受一个字节串为参数,并将其中的内容视为好像在书写时就存在于程序这个位置的代码
1 | |
严格模式下,eval在运行时有其自己的词法作用域,里面的声明无法修改所在的作用域
with
with通常被当作重复引用同一个对象中多个属性的快捷方式,可以不需要重复引用对象本身。本质是将一个对象的引用当作作用域来处理,将对象的属性当作作用域中的标识符,从而创建了一个新的词法作用域
1 | |
性能
JavaScript引擎会在编译阶段进行数项的性能优化。其中有些优化依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。但如果代码中存在eval和with,则只能简单地假设关于标识符位置地判断都是无效的,因为无法在词法阶段分析明确知道eval会接收到什么代码,这些代码会如何修改作用域
作用域和闭包
http://xrcol.github.io/2023/05/14/fd1c98a2ecdf/