javascrip 词法分析详解
JavaScript的高级知识---词法分析
词法分析
词法分析方法:
js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤:
- 分析参数
- 再分析变量的声明
- 分析函数说明
- 函数在运行的瞬间,生成一个活动对象(Active Object),简称AO
- 分析参数
具体步骤如下:
- 函数接收形式参数,添加到AO的属性,并且这个时候值为undefine,例如AO.age=undefine
- 接收实参,添加到AO的属性,覆盖之前的undefine
- 分析变量声明,如var age;或var age=23;
- 如果上一步分析参数中AO还没有age属性,则添加AO属性为undefine,即AO.age=undefine
- 如果AO上面已经有age属性了,则不作任何修改
- 分析函数的声明,如果有function age(){}
把函数赋给AO.age ,覆盖上一步分析的值
代码例子1
这样我们先通过一段代码来理解词法分析:
<script>
function t1(age) {
console.log(age);
var age = 27;
console.log(age);
function age() {}
console.log(age);
}
t1(3);
</script>
词法分析阶段:
- 首先形成Active Object即AO对象
- 第一步:分析形式参数
AO.age = undefine
传入实参即对AO.age=undefine进行覆盖:
AO.age = 3
- 第二步:分析局部变量
存在var age = 27;
这个时候遵循如果AO.age存在值则不作任何修改,按照第一步分析的最后结果AO.age = 3,所以这里不作任何修改即:
AO.age = 3
- 第三步:分析函数的声明,
因为函数中存在function age(){}函数
所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 3即:
AO.age = function age(){}
执行阶段
执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){},所以会打印:
function age(){}
var age=27;给age赋值27
到第二个console.log(age)这个时候age已经重新被赋值27,所以这个时候会打印:
27
function age() 并没有调用所以并不会执行
到第三个console.log(age)这个时候age的值并没有被再次修改,所以这个时候会打印:
27
运行js查看结果如下与我们分析的完全相符:
代码例子2
<script>
function t1(age) {
var age;
console.log(age);
var age = 23;
console.log(age);
function age() {}
console.log(age);
}
t1(22)
</script>
和上面的词法分析过程一样
词法分析阶段:
- 首先形成Active Object即AO对象
- 第一步:分析形式参数
AO.age = undefine
传入实参即对AO.age=undefine进行覆盖:
AO.age = 22
- 第二步:分析局部变量
第一步中最后得到AO.age = 22
所以这里var age;以及var age =23 ,因为AO.age属性已经存在值,所以这个时候遵循如果存在则不作任何修改,即:
AO.age = 22
- 第三步:分析函数的声明,
因为函数中存在function age(){}函数
所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 22即:
AO.age = function age(){}
执行阶段
执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){},所以会打印:
function age(){}
var age=23;给age赋值23
到第二个console.log(age)这个时候age已经重新被赋值23,所以这个时候会打印:
23
function age() 并没有调用所以并不会执行
到第三个console.log(age)这个时候age的值并没有被再次修改,所以这个时候会打印:
23
运行js查看结果如下与我们分析的完全相符:
代码例子3
<script>
function t1(age) {
var age;
console.log(age);
age = 23;
console.log(age);
function age() {
console.log(age);
}
age();
console.log(age)
}
t1(22)
</script>
词法分析阶段:
- 首先形成Active Object即AO对象
- 第一步:分析形式参数
AO.age = undefine
传入实参即对AO.age=undefine进行覆盖:
AO.age = 22
- 第二步:分析局部变量
第一步中最后得到AO.age = 22,所以这里遵循,如果AO.age存在值则不作任何修改即:
AO.age = 22
- 第三步:分析函数的声明
因为函数中存在function age(){console.log(age)}函数
所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 22即:
AO.age = function age(){console.log(age)}
执行阶段
执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){console.log(age)},所以会打印:
function age(){console.log(age)}
age = 23,这个时候会覆盖原来的function age(){console.log(age)},所以第二个console.log(age)会打印:
23
function age() 是一个函数表达式,所以不会做任何操作
age() 这个时候的age还是23,并不是函数表达式,所以这里会报错
运行js查看结果如下与我们分析的完全相符:
这里的提示错误确实也是说age不是一个函数
代码例子4
<script>
function t1(age) {
var age;
console.log(age);
function age() {
console.log(age);
}
age();
console.log(age);
}
t1(23)
</script>
词法分析阶段:
- 首先形成Active Object即AO对象
- 第一步:分析形式参数
AO.age = undefine
传入实参即对AO.age=undefine进行覆盖:
AO.age = 23
- 第二步:分析局部变量
第一步中最后得到AO.age = 23,所以这里遵循,如果AO.age存在值则不作任何修改即:
AO.age = 23
- 第三步:分析函数的声明
因为函数中存在function age(){console.log(age)}函数
所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 23即:
AO.age = function age(){console.log(age)}
执行阶段
执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){console.log(age)},所以会打印:
function age(){console.log(age)}
function age() 是一个函数表达式,所以不会做任何操作
age()这个时候age是一个函数表达式,这里会执行function age(){console.log(age)},这个时候函数里console.log(age),age没有被修改所以还是function age(){console.log(age)},即打印:
function age(){console.log(age)}
最后一个console.log(age)这里的age没有被修改还是function age(){console.log(age)},所以会打印:
function age(){console.log(age)}
运行js查看结果如下与我们分析的完全相符:
代码例子5:
<script>
function t1(age) {
console.log(age);
var age = function () {
console.log(age)
}
age();
console.log(age);
}
t1(23);
</script>
词法分析阶段:
- 首先形成Active Object即AO对象
- 第一步:分析形式参数
AO.age = undefine
传入实参即对AO.age=undefine进行覆盖:
AO.age = 23
- 第二步:分析局部变量
第一步中最后得到AO.age = 23,所以这里遵循,如果AO.age存在值则不作任何修改即:
AO.age = 23
- 第三步:分析函数的声明
这里并没有函数声明表达式
所以最后分析的结果是:
AO.age = 23
执行阶段
执行t1函数,到console.log(age)时,词法分析的最后AO.age=23
所以第一个console.log(age)会打印
23
var age = function () {console.log(age)},这里将var = 23进行覆盖这个时候age是一个函数表达式
age() 正好调用function () {console.log(age)},这个时候这个函数里的console.log(age),age并没有修改还是一个函数表达式,所以会打印
function () {console.log(age)}
最后一个console.log(age)还是打印:
function () {console.log(age)}
运行js查看结果如下与我们分析的完全相符:
代码例子6:
<script>
function t1(age) {
console.log(age);
var age = function age() {
console.log(age);
}
age();
console.log(age);
}
t1(23);
</script>
代码例子6和代码例子5的分析基本一样,结果也是一样:
javascrip 词法分析详解的更多相关文章
- Hanlp分词之CRF中文词法分析详解
这是另一套基于CRF的词法分析系统,类似感知机词法分析器,提供了完善的训练与分析接口. CRF的效果比感知机稍好一些,然而训练速度较慢,也不支持在线学习. 默认模型训练自OpenCorpus/pku9 ...
- 转载:C/C++源代码到可执行程序的过程详解
C/C++源代码到可执行程序的过程详解 编译,编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格 ...
- 常见 jar包详解
常见 jar包详解 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期 ...
- C编译器、链接器、加载器详解
摘自http://blog.csdn.net/zzxian/article/details/16820035 C编译器.链接器.加载器详解 一.概述 C语言的编译链接过程要把我们编写的一个c程序(源代 ...
- ctags使用说明详解
ctags使用说明详解 一.ctags是干什么的 ctags的功能:扫描指定的源文件,找出其中所包含的语法元素,并将找到的相关内容记录下来. 我用的是Exuberant Ctags 二.ctags可以 ...
- Oracle建立全文索引详解
Oracle建立全文索引详解1.全文检索和普通检索的区别 不使用Oracle text功能,当然也有很多方法可以在Oracle数据库中搜索文本,比如INSTR函数和LIKE操作: SELECT *FR ...
- 2. 知识图谱-命名实体识别(NER)详解
1. 通俗易懂解释知识图谱(Knowledge Graph) 2. 知识图谱-命名实体识别(NER)详解 3. 哈工大LTP解析 1. 前言 在解了知识图谱的全貌之后,我们现在慢慢的开始深入的学习知识 ...
- (转)总结之:CentOS 6.5 MySQL数据库的基础以及深入详解
总结之:CentOS 6.5 MySQL数据库的基础以及深入详解 原文:http://tanxw.blog.51cto.com/4309543/1395539 前言 早期MySQL AB公司在2009 ...
- [转]JavaScript异步机制详解
原文: https://www.jianshu.com/p/4ea4ee713ead --------------------------------------------------------- ...
随机推荐
- Android适配器Adapter的学习
Android中有很多的适配器,首先看看这些适配器的继承结构 这些适配器中,BaseAdapter用的最多,也用的最熟,先放过他,从ArrayAdapter开始 一个listAdapter用来管理一个 ...
- mongo_2 $in 和 $all 区别
in 只需满足( )内的某一个值即可, 而$all 必须满足[ ]内的所有值, > db.table1.find({}); { "_id" : ObjectId(" ...
- 2014蓝桥杯B组初赛试题《六角填数》
题目描述: 如图[1.png]所示六角形中,填入1~12的数字. 使得每条直线上的数字之和都相同. 图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少? 请通过浏览器提交 ...
- C++中内存区域的划分
栈存储区 那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区.里面的变量通常是局部变量.函数参数等. 堆存储区(自由存储区) 那些由new或者malloc分配的内存块,他们的释放编译器 ...
- ubuntu下安装配置apache2(含虚拟主机配置)
在Ubuntu14.14中安装apache 安装指令: sudo apt-get install apache2 安装结束后: 产生的启动和停止文件是: /etc/init.d/apache2 启动: ...
- jqgrid控件列分组
<%-- builed by manage.aspx.cmt [ver:2014.48.11] at 2014/10/11 16:48:33 --%> <%@ Page Langua ...
- css总结20:TCP通信协议WebSocket
HTML5 WebSocket 1 介绍: WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. 在WebSocket API中,浏览器和服务器只需要做一个握手的动 ...
- 第07章-Spring MVC 的高级技术
Spring MVC 的高级技术 1. Spring MVC配置的替代方案 1.1 自定义DispatcherServlet配置 AbstractAnnotationConfigDispatcherS ...
- Android getDimension,getDimensionPixelOffset,getDimensionPixelSize
1.例如在onMeasure(int , int)方法中可能要获取自定义属性的值.如: TypedArray a = context.obtainStyledAttributes(attrs, R.s ...
- 利用Response.Buffer做类似异步效果
在page_load加入以下代码 Response.Buffer = false; //这句话非常重要 for (int i = 0; i < 10; i++) { Thread.Sleep( ...