js的高级知识---词法分析
词法分析
词法分析方法:
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的分析基本一样,结果也是一样:

总结
总之,按照上述最开始写的方法分析,都能分析出结果来
js的高级知识---词法分析的更多相关文章
- JavaScript的高级知识---词法分析
JavaScript的高级知识---词法分析 词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 函数在运行的瞬间, ...
- 第十九篇 js高级知识---词法分析和AO 链
上面一篇文章说了js的作用域链,这一节算是对上面的延申,有一个典型的例子,首先看原来的一段代码: var name = "test"; function t() { var b = ...
- js高级知识---词法分析和AO 链
转载自https://www.cnblogs.com/OceanHeaven/p/4957704.html 上面一篇文章说了js的作用域链,这一节算是对上面的延申,有一个典型的例子,首先看原来的一段代 ...
- python成长之路【第十六篇】:JavaScript的高级知识---词法分析
一.词法分析方法 js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 二.具体步骤如下: 函数在运行的瞬间,生成一个活动对象(Active O ...
- 第十八篇 js高级知识---作用域链
一直有想法去写写js方面的东西,我个人是最喜欢js这门语言,喜欢的他的自由和强大,虽然作为脚本语言有很多限制的地方,但也不失为一个好的语言,尤其是在H5出现之后.下面开始说说js的方面的东西,由于自己 ...
- css+js+html基础知识总结
css+js+html基础知识总结 一.CSS相关 1.css的盒子模型:IE盒子模型.标准W3C盒子模型: 2.CSS优先级机制: 选择器的优先权:!important>style(内联样式) ...
- 自理一遍android 高级知识
之后按目录得复习巩固 目录: 客卓高级知识整理 1 移动架构 1.1 素养与基础 1.1.1 主流设计模式 创建型 行为型 结构型 1.1.2 UML 1.1.3 设计原则 1.1.4 AOP架构 1 ...
- DataBase MongoDB高级知识-易使用
MongoDB高级知识-易使用 mongodb是一个面向文档的数据库,而不是关系型数据库.不采用关系模型主要是为了获取更好的扩展性.当然还有其他的一些好处. 与关系型数据库相比,面向文档的数据库不再有 ...
- DataBase MongoDB高级知识-易扩展
MongoDB高级知识-易扩展 应用程序数据集的大小正在以不可思议的速度增长.随着可用宽带的增长和存储器价格的下跌,即使是一个小规模的应用程序,需要存储的数据也可能大的惊人,甚至超出了很多数据库的处理 ...
随机推荐
- 用C#通过正则表达式截取字符串中符合条件的子字符串
仅仅作为简单的记录,不多说直接上代码(仅测试使用): private void Test() { Regex ConnoteA = new Regex("^[a-zA-Z]\\d{8}$&q ...
- python lambda
匿名函数和lambda: lambda [args1,[args2]] : expression python 使用lambda来创建匿名函数,匿名函数不需要以标准的方式进行创建,但是作为函数,它们也 ...
- 逗号分割符--字段中含逗号等情况的解析方法Java实现
最近在处理文本字符串时,没一行数据都是按照逗号分割的,每个字段值一般情况是带有双引号的,但是有的字段值里面还包含逗号,甚至有的字段就没有双引号,这个分割起来就有点麻烦了 下面说一下我解决方法,如果谁有 ...
- BZOJ2527: [Poi2011]Meteors
补一发题解.. 整体二分这个东西,一开始感觉复杂度不是很靠谱的样子 问了po姐姐,说套主定理硬干.. #include<bits/stdc++.h> #define ll long lon ...
- ZeroMQ接口函数之 :zmq_ctx_set - 设置环境上下文属性
ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_ctx_set zmq_ctx_set(3) ØMQ Manual - ØMQ/3.2.5 Name zmq_ct ...
- java接口的嵌套
java接口 1.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值 2.接口中的方法默认都是 public abstract ...
- Objective-O Runtime 运行时初体验
Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...
- C#网络编程之---TCP协议的同步通信(二)
上一篇学习日记C#网络编程之--TCP协议(一)中以服务端接受客户端的请求连接结尾既然服务端已经与客户端建立了连接,那么沟通通道已经打通,载满数据的小火车就可以彼此传送和接收了.现在让我们来看看数据的 ...
- HTTP,FTP,TCP,UDP及SOCKET
一.TCP/IP协议简析TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层:网络层:IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议传输层:TCP协议与UDP协议应用层:F ...
- Clustering Methods: Benefits and Limitations
COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION