作用域和闭包(一)
一、作用域是什么?
1、概念:设计好一套规则来存储变量,并且之后可以方便找到这些变量。(并且之后对这个值可以进行访问和修改。)
2、传统编译语言流程:程序中的源代码在执行之前,会经历以下三个步骤,统称为“编译”;
(1)分词/词法分析。(这个·过程会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元。)
例:var a = 2; //被分解成 var、a、=、2、;这些词法单元。(空格是否被当作词法单元,却决于它在语言中的意义);
(2)解析/语法分析。
(3)代码生成。
概念:将AST转换为可执行代码的过程称为代码生成。(就是将var a = 2;的AST转化为一组机器指令,用来创建一个a的变量并将一个值·存储在a中。)
任何JavaScript代码在执行之前都要进行编译
3、理解作用域
(1)对var a = 2;进行处理的三大成员
引 擎:从头到尾负责整个JavaScript程序的编译和执行过程。
编译器:负责语法分析及代码生成。
作用域:负责收集并维护由所有生命的标识符(变量)组成的一系列查询,并实施一套非常严厉的规则,确定当前执行的代码对这些标识符的访问权限。
(2)编译处理过程。
首先,遇到 var a ,编译器会询问作用域中是否已经有一个该名称的变量存在于同一个作用域的集合中。如果是,编译器会忽略该声明,继续进行编译;否则,它会要求作用域在当前
域的集合中生命一个变量,并命名为a;
其次,编译器会为引擎生成运行时所需的代码,这些代码备用来处理a = 2;这个赋值操作。引擎运行时会首先访问作用域,当前作用域集合中是否存在一个叫做a的变量。如果是,引
擎就会使用这个变量;如果不是,引擎会继续查找该变量。(找不到,会抛出一个异常。)
(3)引擎对a进行的左侧查询(LSH,赋值操作的目标),右侧查询(RHS,赋值操作的源头);即变量出现在赋值操作的左侧时,进行LSH查询,出现在右侧时进行RHS查询。
RHS理解为“得到某某的值”,LHS试图找到变量的容器本身,并对其赋值。
RHS 例:console.log(a); 这里用了a,却没赋值,只是查找a的值,并传给console.log(..)
LHS 例:a = 2; 并不关心当前的值,只是想为=2这个赋值操作找到个目标。
例: function foo(a){
console.log(a);
}
foo(2);
其中既有左侧查询,又有右侧查询。有个隐式转换,a = 2;
4、作用域嵌套
引擎从当前的执行作用于开始查找变量,如果找不到,就向上一级继续查找。当到全局作用域时,不管有没有找到,都会停止。(当RHS查询在所有嵌套的作用域中遍寻不到所需的
变量,引擎就会抛出一个ReferenceError异常。)如果在“不在严格模式下,左侧查询,查不到该变量,就会创建一个变量。”(严格模式禁止自动或隐式的创建全局变量);严格模式
下,也会抛出ReferenceError异常;如果引用null或者undefined类型中的值,会抛出TypeError错误。
二、词法作用域
未完待续。。。。
原文地址:https://www.cnblogs.com/yaosusu/p/11407737.html