js词法分析
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的分析基本一样,结果也是一样:
总结
总之,按照上述最开始写的方法分析,都能分析出结果来
js词法分析的更多相关文章
- js作用域和词法分析
都知道js中不存在类似于c++等语言的块级作用域,例如for循环中定义的变量,其实是属于当前对象下的属性,同一对象下可以随便访问.只有函数可以限定一个变量的作用范围,即函数才是变量的作用域. 对于函数 ...
- js 变量提升和函数提升原理
关于js的变量,开始的时候我们都会被告知,变量声明应该在引用该变量之前.关于为什么要这样做呢,开始的时候本着会用就行的目的,也没去深究.不过后来经常会发现一些让人很费解的..姑且称为现象吧.先看一段代 ...
- js作用域的相关知识
众所周知,在ES6之前,JavaScript是没有块级作用域的,如下图所示: 学过其他语言的同学肯定有点诧异,为什么会这样呢?因为js还是不同于其他语言的,在ES5中,只有全局作用域和函数作用域,并没 ...
- 深入浏览器工作原理和JS引擎(V8引擎为例)
浏览器工作原理和JS引擎 1.浏览器工作原理 在浏览器中输入查找内容,浏览器是怎样将页面加载出来的?以及JavaScript代码在浏览器中是如何被执行的? 大概流程可观察以下图: 首先,用户在浏览器搜 ...
- 前端-js-长期维护
############### JS简介和JS引入 ################ <!DOCTYPE html> <html lang="en" ...
- js的高级知识---词法分析
词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 具体步骤如下: 函数在运行的瞬间,生成一个活动对象(Active ...
- 第十九篇 js高级知识---词法分析和AO 链
上面一篇文章说了js的作用域链,这一节算是对上面的延申,有一个典型的例子,首先看原来的一段代码: var name = "test"; function t() { var b = ...
- js高级知识---词法分析和AO 链
转载自https://www.cnblogs.com/OceanHeaven/p/4957704.html 上面一篇文章说了js的作用域链,这一节算是对上面的延申,有一个典型的例子,首先看原来的一段代 ...
- JS中script词法分析
核心:JS中的script是分段执行的. <script> var i = 10; </script> <script> alert(i); </script ...
随机推荐
- ECharts学习(4)--仪表盘
1. ECharts中的仪表盘,要使用这个图表时把series中的type属性修改成'gauge',然后在detail中设置仪表盘详情,用于显示数据.最常用的是formatter(格式化函数或者字符串 ...
- mongodb未授权访问漏洞
catalogue . mongodb安装 . 未授权访问漏洞 . 漏洞修复及加固 . 自动化检测点 1. mongodb安装 apt-get install mongodb 0x1: 创建数据库目录 ...
- windows使用git时出现:warning: LF will be replaced by CRLF
windows中的换行符为 CRLF, 而在linux下的换行符为LF,所以在执行add . 时出现提示: 执行以下代码 $ rm -rf .git // 删除.git $ git config -- ...
- webapi-创建项目
- 一个简单的 Web 服务器 [未完成]
最近学习C++,linux和网络编程,想做个小(mini)项目. 就去搜索引擎, 开源中国, Sourceforge上找http server的项目. 好吧,也去了知乎. 知乎上程序员氛围好, ...
- Django基础,Day2 - 编写urls,views,models
编写views views:作为MVC中的C,接收用户的输入,调用数据库Model层和业务逻辑Model层,处理后将处理结果渲染到V层中去. polls/views.py: from django.h ...
- SpringMVC学习记录1
起因 以前大三暑假实习的时候看到公司用SpringMVC而不是Struts2,老司机告诉我SpringMVC各种方便,各种解耦. 然后我自己试了试..好像是蛮方便的.... 基本上在Spring的基础 ...
- 仿淘宝分页按钮效果简单美观易使用的JS分页控件
分页按钮思想: 1.少于9页,全部显示 2.大于9页,1.2页显示,中间页码当前页为中心,前后各留两个页码 附件中有完整例子的压缩包下载.已更新到最新版本 先看效果图: 01输入框焦点效果 ...
- http://875880923.iteye.com/blog/1963400
已经接触了一段时间的ACM(详见百度百科)了,每回刷杭电oj的题累了的时候,就喜欢去看Ranklist里面的排名,看看前面的牛人的格言,让自己有一点憧憬.有一天突然好奇杭电上的人做的总题数的数量与人数 ...
- qt5中文代码编码编译问题
qt中文代码用vs2010编译问题解决 总结说就是qt5默认UTF8不支持微软默认的ANSI(GB2312/GBK).解决办法是把中文字符串全部用 QString::fromLocal8Bit() 封 ...