【读书笔记】你不知道的JavaScript(上卷)--作用域是什么
第一章 作用域
1、理解作用域
几个名词的介绍
引擎:从头到尾负责整个JavaScript程序的编译及执行过程
编译器:负责语法分析及代码生成器等脏活累活
作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
对var a = 2;进行分解,了解引擎等是如何工作。
编译器首先将这段程序分解成词法单元,然后将词法单元解析成一个树结构。但是当编译器开始进行代码生成时,它对这段程序的处理方式会和预期的有所不同。
编译器会进行如下处理
1)遇到var a,编译器会询问作用域是否已经有一个该名称的变量存在于同一作用域的集合中。如果是,编译器会忽略该声明,继续2进行编译;否则它会要求作用域在当前作用域的集合中声明一个新变量,并命名为a。
2)接下来编译器会为引擎生成运行时所需的代码,这些代码被用来处理a = 2这个赋值操作。引擎运行时会首先询问作用域,在当前的作用域集合中是否存在一个叫作a的变量。如果是,引擎就会使用这个变量;如果否,引擎就会继续查找该变量。如果引擎最终找到了a变量,就会将2赋值给它。否则引擎就会抛出异常。
总结:变量的赋值操作会执行两个动作,首先编译器会编译当前作用域中声明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对他赋值。
2、编译器的LHS和RHS
变量出现在赋值操作的左侧时进行LHS查询,出现在右侧时进行RHS查询
考虑以下代码:
console.log(a);
其中对a的引用是一个RHS引用(因为这里是将a的值传递给console.log(..))。
相比之下,例如:
a = 2;
这里对a的引用则是LHS引用,将2的值赋给a。
总结:LHS和RHS的含义是 "赋值操作的左侧或右侧" 并不一定意味着就是 "=赋值操作符的左侧或右侧" 。赋值操作还有其他几种形式,因此在概念上最好将其理解为 "赋值操作的目标是谁(LHS)" 以及 "谁是赋值操作的源头(RHS)" 。
考虑下面程序,其中既有LHS也有RHS引用:
function foo () {
console.log(a); //2
}
foo(2);
最后一行 foo(..) 函数的调用需要对foo进行RHS引用,意味着 "去找到foo的值,并把它给我" 。并且(..)意味着foo的值需要被执行,因此它最好真的是一个函数类型的值!
代码中隐式的a = 2操作可能很容易被忽略,这里进行了一次LHS查询。
小测试:
function foo(a) {
var b = a;
return a + b;
}
var c = foo(2);
1)、找到所有的LHS查询
c = ..;、a = 2(隐式变量分配)、b = ..
2)、找到所有的RHS查询
foo(2..、=a;、a..、..b
3、作用域嵌套
当一个块或函数嵌套在另外一个块或函数时,就会发生了作用域的嵌套。因此,在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域(也就是全局作用域)为止。
4、异常
在变量还没有声明(在任何作用域中都无法找到该变量)的情况下,LHS和RHS两种查询的行为是不一样的。
考虑如下代码:
function foo(a) {
console.log(a + b);
b = a;
}
foo(2);
第一次对b进行RHS查询时无法找到该变量的。也就是说,这是一个 "未声明" 的变量,因为在任何相关的作用域中都无法找到它。
如果RHS查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出ReferenceError异常。值得注意的是,ReferenceError是非常重要的异常类型。
相比较之下,当引擎执行LHS查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是程序运行在非 "严格模式" 下。
接下来,如果RHS查询找到了一个变量,但是你尝试对这个变量进行不合理的操作,比如试图对一个非函数类型的值进行函数调用,或者引用null或undefined类型的值中的属性,那么引擎会抛出另外一个类型异常,叫作TypeError。
ReferenceError同作用域判别失败相关,而TypeError则代表作用域判别成功了,但是对结果操作是非法或不合理的。
【读书笔记】你不知道的JavaScript(上卷)--作用域是什么的更多相关文章
- 读书笔记-你不知道的JavaScript(上)
本文首发在我的个人博客:http://muyunyun.cn/ <你不知道的JavaScript>系列丛书给出了很多颠覆以往对JavaScript认知的点, 读完上卷,受益匪浅,于是对其精 ...
- 你不知道的JavaScript上卷笔记
你不知道的JavaScript上卷笔记 前言 You don't know JavaScript是github上一个系列文章 初看到这一标题的时候,感觉怎么老外也搞标题党,用这种冲突性比较强的题目 ...
- 你不知道的javaScript上卷(第一章 作用域是什么)
在写这篇博客时这本书我已经是看过一遍了,为了加深印象和深入学习于是打算做这系列的前端经典书籍导读博文,大家如果觉得这本书讲的好可以自己买来看看,我是比较喜欢看纸质版书的,因为这样才有读书的那种感觉. ...
- 《你不知道的 JavaScript 上卷》 学习笔记
第一部分: 作用域和闭包 一.作用域 1. 作用域:存储变量并且查找变量的规则 2. 源代码在执行之前(编译)会经历三个步骤: 分词/此法分析:将代码字符串分解成有意义的代码块(词法单元) 解析/语法 ...
- 读《你不知道的JavaScript(上卷)》后感-作用域闭包(二)
github原文 一. 序言 最近我在读一本书:<你不知道的JavaScript>,这书分为上中卷,内容非常丰富,认真细读,能学到非常多JavaScript的知识点,希望广大的前端同胞们, ...
- 读《你不知道的JavaScript(上卷)》后感-浅谈JavaScript作用域(一)
原文 一. 序言 最近我在读一本书:<你不知道的JavaScript>,这书分为上中卷,内容非常丰富,认真细读,能学到非常多JavaScript的知识点,希望广大的前端同胞们,也入手看看这 ...
- 【你不知道的javaScript 上卷 笔记3】javaScript中的声明提升表现
console.log( a ); var a = 2; 执行输出undefined a = 2; var a; console.log( a ); 执行输出2 说明:javaScript 运行时在编 ...
- 你不知道的JavaScript之作用域
什么是作用域 编译原理 分词/词法分析 这个过程会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代 码块被称为词法单元(token) 解析/语法分析 这个过程是将词法单元流(数组)转 ...
- JavaScript词法作用域—你不知道的JavaScript上卷读书笔记(一)
前段时间在每天往返的地铁上抽空将 <你不知道的JavaScript(上卷)>读了一遍,这本书很多部分写的很是精妙,对于接触前端时间不太久的人来说,就好像是叩开了JavaScript的另一扇 ...
- JS闭包—你不知道的JavaScript上卷读书笔记(二)
关于闭包,初学者会被绕的晕头转向,在学习的路上也付出了很多精力来理解. 让我们一起来揭开闭包神秘的面纱. 闭包晦涩的定义 看过很多关于闭包的定义,很多讲的云里雾里,晦涩难懂.让不少人以为闭包是多么玄乎 ...
随机推荐
- Kudu安装(官网推荐的步骤)(installing Kudu using parcels or packages)
不多说,直接上干货! Kudu安装前的建议说明(博主推荐) Kudu官网推荐的步骤: 本篇博文是installing Kudu using parcels or packages的方式. http:/ ...
- 04-spring中的aop演示
1 xml配置 1 导包 2 准备对象 package www.test.service; public interface UserService { public abstract void ad ...
- rsync 命令中的路径斜线
rsync命令大家都知道,但是其中的一个小细节比较容易被忽略,那就是 路径结尾的 "/" ,在路径的结尾有没有斜线,结果是大不同的.现举例说明: 假设现有两个目录,一个名为sour ...
- http method and status code
http method HEAD: 只返回相应的header POST: 一般用于提交表单 PUT: 向Web服务器上传文件 GET: 查 DELET: 删除 status code 1xx与2xx: ...
- 通过一个例子,总结下检测数组属性的N种方法
判断arr数组里是否含有a,有a返回1;没有返回2var arr = [{a:1,b:2,c:3},{q:1,w:2,e:3},{s:4,g:5,i:9},{b:2,v:3,u:4}]; 检测属性的3 ...
- 再次梳理css3动画部分知识
1.transform: 适用于2D或3D转换的元素 transform-origin:元素的位置点 css3转换(2D转换和3D转换):可以对元素进行移动.缩放.转动.拉长或拉伸. 2D转换:tra ...
- webConfig中<customErrors>节点配置
发布在远程计算机上的网站调试问题: 通常情况下我们会设置错误页,不让用户看到错误信息 这种WebConfig的配置方法是: <configuration> <system.web&g ...
- IsBackground对线程的重要作用
要点: 1.当在主线程中创建了一个线程,那么该线程的IsBackground默认是设置为FALSE的. 2.当主线程退出的时候,IsBackground=FALSE的线程还会继续执行下去,直到线程执行 ...
- Spring课程 Spring入门篇 4-1 Spring bean装配(下)之bean定义及作用域注解实现
课程链接: 1 概述 2 代码演练 3 代码解析 1 概述 1.1 bean注解相关 a context:component-scan标签使用 问:该标签的作用是什么? 答:该标签作用是支持注解,在x ...
- 零基础逆向工程39_Win32_13_进程创建_句柄表_挂起方式创建进程
1 进程的创建过程 打开系统 --> 双击要运行的程序 --> EXE开始执行 步骤一: 当系统启动后,创建一个进程:Explorer.exe(也就是桌面进程) 步骤二: 当用户双击某一个 ...