作用域那点事
2020-08-08 19:10
465 查看
作用域
用来声明,访问和修改变量的上下文,定义了变量的访问权限和查找机制。
作用域分类:
- 全局作用域 (整个JS运行环境,最顶层作用域,其声明的函数、变量等都是全局的)
- 函数作用域 (函数执行时会创建作用域)
- 块级作用域 ({ }大括号在 let、const关键字特性产生的作用域)
JS属于编译语言,逐行执行;编译的过程分为三部分:
- 分词/词法分析。
- 解析/把词法分析转换成AST(抽象语法树)。
- 代码生成/把AST转成可执行代码。
示例:
var a = 1;
编译过程:
- 分成var a、a=1;两部分进行分析。
- 查看当前作用域是否有a,如果有就忽略,如果没有就创建变量a。
(var、function声明的变量会在当前作用域下进行变量提升) - 赋值操作,首先查看当前作用域下是否有变量a,要是不存在变量a就会报错,要是存在进行赋值;其次如果是作用域嵌套的情况,当前作用域下不存在变量a,就会向外层作用域查找,直到全局作用域,如果不存在变量a就会报错。
执行过程:
- 执行var a语句进行查找a变量,这个过程叫做LHS(左侧为查找目标)。
- 执行a = 1赋值操作,过程叫做RHS(右侧为目标查找的目的)。
- 进行RHS必然会进行LHS。
注意:取值和赋值都是RHS,变量声明和形参是LHS;RHS和LHS发生在执行过程中。
示例:
function foo(a) { var b = a; return a + b } var c = foo(2)
3处LHS查询:
- var c 声明
- var b 声明
- 形参 a 声明
4处RHS查询:
- foo(2) 取值foo并执行
- var b = a语句,取值a
- a + b语句,取值a
- a + b语句,取值b
作用域嵌套:
当一个块或函数嵌套在另一个块或函数里,就发生了作用域嵌套。
作用域嵌套下变量的查找规则:
查找变量时如果当前作用域里没有找到,就会向外层 56c 作用域查找,直到找到该变量或到全局作用域为止,如果没找到就会报错。
作用域嵌套查找变量的特点:
从内往外,LHS和RHS都会在当前作用域进行,LHS只有当前作用域下没有找到所需变量,才会向外层作用域查找。
变量提升对LHS的影响:
- 变量提升发生在编译过程,一个没有用var声明的变量不会进行变量提升,在该变量之前进行RHS,会报ReferenceError异常is not defined。
- 用var声明的变量会进行变量提升,提升到当前作用域的最顶部,其值是undefined,因此在变量前进行取值不会报错。
- 非严格模式下对没有用var关键字声明的变量语句之前进行RHS,报ReferenceError异常。如果是之后进行RHS,会先进行LHS,如果当前作用域还是全局作用域下都没有找到,会自动创建一个全局变量并返回,严格模式下LHR查询失败时,并不会创建一个全局变量并返回,报ReferenceError异常。
变量的访问权限问题:
- 块级作用域里的变量外层作用域是无法访问,变量是指由let,const。
- 函数的形参和变量,内部函数是外层作用域无法访问,属于局部变量。变量是指由let,const,var,funct ad8 ion声明的。
部分参考:
《你不知道的JavaScript》
相关文章推荐
- c++中 string与string.h 的作用和区别
- command &>/dev/null 的作用
- Adapter的作用就是ListView界面与数据之间的桥梁
- Fragment在xml中但作用不是显示view
- SSH的作用
- 零基础学python-16.6 嵌套作用域
- final关键字的作用
- jsp的useBean作用域问题
- 光耦的作用及工作原理
- 聚合物电容作用原理与基础
- ServletContextListener作用
- PHP中set_magic_quotes_runtime()和get_magic_quotes_gpc函数的作用
- PS中“曲线”【ctrl+M】的作用【加强对曲线的使用】
- java中各种@的作用
- #line 的作用是改变当前行数和文件名称
- 四个作用域
- java在处理异常时finally语句的作用
- 数据结构和算法[精选]----说明一下这个分类之后的作用
- 理解ES6: 块作用域
- Java中return的作用