深入理解javascript之作用域

我所理解的作用域就是你所申明的变量、函数住在哪里?程序在需要的使用如何能够找到他们?而设计的这套规则即为作用域
而javascript是一门解释性语言,是在执行的前很短时间内编译再执行。
从以下方面来分析javascript的作用域

编译原理

词法分析: 将程序字符串分解一个一个独立的词法单元; 如下
	var answer = 6 * 7;
拆分:var | answer | = | 6 | * | 7
语法分析:将词法数组转换成抽象的语法树AST[Abstract Syntax Tree]

代码生成: 将AST转换成可执行代码的过程称为代码生成

编译规则

  • 遇到变量声明,优先询问作用域下是否存在一个该变量名称在同一个作用域集合中. 如果是,则忽略;否则在当前作用于集合中添加
  • 遇到表达式执行【a=2】,引擎会优先询问作用域下是否存在此变量,如果是,引擎使用这个变量,如果否,则继续查找;如果找不到,则抛出引用错误异常

赋值的两个概念 LHS / RHS

  • RHS[retrieve his source value] LHS[]

  • LHS与RHS:javascript引擎的两种查找类型,含义是赋值操作的左侧与右侧。

  • LHS:对哪个赋值就对哪个进行LHS引用,可以理解为赋值操作的目标。

  • RHS:需要获取哪个变量的值,就对哪个变量的值进行RHS引用,理解为赋值操作的源头。

 分析以下函数LHS与RHS个数
 function foo(a){
	var b=a;
	rerurn a+b;
 }
 var c=foo(2);

为什么要引擎要使用两种查找类型?
处理方式不同; 非严格模式下,RHS对未声明的变量抛出现引用错误

词法作用域

作用域气泡
每个位置的作用域都会生成一个层级关系的气泡,引擎通过层级关系的气泡进行查找,直到查找就停止

遮蔽效应
最近的作用域气泡会遮蔽外部的作用域气泡里的变量
但全局作用域下的变量声明,可以通过window属性来访问 window.a

函数作用域和块作用域

函数作用域 【
	IIFE (Immediately Invoked Function Expression)
	UMD(Universal Module Definition)
】
	IIFE (Immediately Invoked Function Expression)
	(function(global){
		...
		...
	})(window);
	UMD(Universal Module Definition)
	(function(global, def){
		...
		...
		def(global);
	})(window, function handler(window) {
		...
		...
	} );
块作用域: 针对for if while代码块里`var`定义的变量或函数声明并不会只存在于块中 
而用let来声明可以使生成块级作用域

声明提升

  • 优先函数声明整体提升, 后来者会覆盖
  • 变量声明整体提升

代码分享

for(var i =0 ;i < 10; i++ ) {
	setTimeout(function() {
		console.info(i);
	}, 100);
}
for(let i =0 ;i < 10; i++ ) {
	setTimeout(function() {
		console.info(i);
	}, 100);
}
posted @ 2020-04-29 09:35  pengsn  阅读(180)  评论(0编辑  收藏  举报