你不知道的JavaScript(上卷)作用域和闭包

第一章 作用域是什么

提示:这里只是作者的学习,如果出现理解错误欢迎指正

1.1 编译原理
1.2 理解作用域
1.3 作用域嵌套
1.4 异常
1.5 小结



前言

随着前端的不断发展,这项行业也越来越卷,虽然面试的时候都会问JS,但是他们问的JS都足够刁钻,所以本文就介绍了《你不知道的JavaScript》这一书,以卷治卷。

概念:几乎所有的编程语言都有的基本功能就是能储存变量当中的值,并且在之后能对当前值进行访问和修改。为了方便的找到这些变量,就会设置一套良好的规则来存储变量,这套规则被称为作用域


1.1 编译原理

JavaScript引擎进行编译的步骤和传统编译语言非常类似,在某些环节可能更复杂
传统编译语言的流程中,程序中的一段源代码在执行之前会经历三个步骤,统称为“编译”

  1. 分词/词法分析

    提示:个人理解

// 比如,var a = 2 会将它分割为"var"、"a"、"="、"2",空格是否会被做成词法单元取决于空格在此是否有意义
// 个人感觉词法分析就是将字符流转化成记号流
var a = 2
//转化为
list= [
	{type:'Keyword',value:'var'},
	{type:'Identifier',value:'a'},
	{type:'Punctuator',value:':'},
	{type:'Numberic',value:'2'}
]
  1. 解析/语法分析
// 换成的抽象语法树
json = {
	"type":"Program",
	"start":0, // 开始字符标识位置
	"end":9, // 结束字符标识位置
	"body":[
		{
			"type":"VariableDeclaratoration",
			"start":0, // 开始字符标识位置
			"end":9, // 结束字符标识位置
			"declarations":[
				{
					"type":"VariableDeclarator",
					"start":4, // 开始字符标识位置
					"end":9, // 结束字符标识位置
					"id":{
						"type":"Identifier",
						"start":4, // 开始字符标识位置
						"end":5, // 结束字符标识位置
						"name":"a",
					},
					"mit":{
						"type":"Literal",
						"start":8, // 开始字符标识位置
						"end":9, // 结束字符标识位置
						"value":"2",
						"row":"2",
					}
				}
			],
			"kind":"var"
		}
	],
	"sourceType":"module"
}
  1. 代码生成
代码生成:引擎=>内存=>变量a=>赋值a给变量a

总结:JavaScript引擎会在语法分析和代码生成环节有特定的步骤来对性能进行优化,包括对冗杂元素进行优化等。JavaScript在执行一段代码前都要进行编译,然后做好执行他的准备,通常情况下它会马上执行。


1.2 理解作用域

1.2.1 演员表

  1. 引擎
    从头到尾负责整个JavaScript程序的编译及执行过程
  2. 编译器
    负责语法分析及代码生成
  3. 作用域
    负责收集并维护由所有声明的变量组成的一系列查询,并实施一套严格的规则,确定当前执行代码对这些变量的访问权限

1.2.2 对话

总结:变量赋值

变量赋值

1.2.3 编译器有话说

RHS查询:取到它的源值,简单的说RHS只是引用不涉及到赋值
LHS查询:是进行赋值操作

function foo(a){
	console.log(a); // 简单的引用a,RHS查询
}
foo(2)  // foo()这个函数是进行引用了具名函数foo所以是RHS查询,但是里面有隐性的LHS查询,因为foo(2)里面的2传给a了所以就有了a=2的LHS查询

总结: (var foo = function() ) 如果进行声明,则不能单纯的理解做了LHS查询赋值,因为引擎不会有线程专门用来讲一个函数值分配给foo

1.2.4 引擎和作用域的对话

function foo(a){
	console.log(a) // 2
}
foo( 2 )

总结:
引擎=>foo RHS引用
作用域=>编译器声明了,它是一个函数,给
引擎=>执行foo
引擎=>a进行LHS引用
作用域=>foo的一个形式参数,给
引擎=>把2赋值给a
引擎=>consoleRHS引用
作用域=>console是个内置函数,给
引擎=>找到log()
引擎=>找到a的RHS引用
作用域=>变量没变,给
引擎=>把a的值2传递给log()

1.2.5 小检测

function foo(a){
	var b=a;
	return a+b
}
var c =foo(2)

总结:
LHS:
c=foo(2) foo(a =2) b=a
RHS:
foo(2) b=a(a) a+b(a和b各一次)


1.3 作用域嵌套

总结:
当发生查询时,作用域的查询是
当前作用域=>上级作用域…=>全局作用域=>停止


1.4 异常

总结:
当RHS查询不到结果,变量没有声明,引擎抛出ReferenceError,ReferenceError是非常重要的异常类型
当LHS查询,在全局也不能找到目标变量,全局作用域就会创建一个具有该名称的变量返回给引擎
(注:非严格模式,严格模式下也抛出ReferenceError)
RHS查询一个非函数类型的值进行函数调用或者引用null或者undefined类型的值中的属性,引擎会抛出TypeError
ReferenceError是作用域判别失败,TypeError是作用域判别成功,操作是非法的


总结

提示:这里对文章进行总结:

作为程序员,我是真觉的JavaScript是一本好书,因为我从中学到了很多,也了解了我之前很多没有关注到的细节,就像一个简单的异常抛出我们每天都在打交道,可我从来没有深究过。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值