js高级知识---词法分析和AO 链
转载自https://www.cnblogs.com/OceanHeaven/p/4957704.html
上面一篇文章说了js的作用域链,这一节算是对上面的延申,有一个典型的例子,首先看原来的一段代码:
var name = "test";
function t() {
var b = 1;
if (b === 1) {
var name = "test1";
} else {
var name = "test2";
}
console.log(name);
}
t();
这段代码的结果是test1
这个肯定是没有什么问题了,但是如果把代码作如下修改:
修改1:
var name = "test";
function t() {
console.log(name);
var name = "test1";
console.log(name);
}
t(); 修改2:
var name = "test";
function t() {
console.log(name);
/***********
// var b = 1;
// if (b === 1) {
// var name = "test1";
// } else {
// var name = "test2";
// }
// console.log(name);
******************/
}
t();
这两个都是基于原来的代码修改,运行的结果分别是undefine,test1和test,噫!
这个是修改1后的输出:
这个是什么原因呢?原来在js运行前会有一个类似编译的过程------词法分析。首先看下记法分析的过程,词法分析主要分三个步骤:
1、先分析参数
2、再分析变量的声明
3、分析函数说明
具体的步骤:
0:函数的在运行的瞬间,生成一个活动对象(Active Object)就是所谓的AO
1:分析参数
1-1:函数接收参数,添加到AO的属性上面,值全部都是undefine,如AO.age=undefine
1-2:接收实参,形成AO对应的属性值
2:分析变量声明,如var age,
2-1:如果AO上还没有age属性,则添加AO 属性,值是undefine
2-2:如果AO 上面已经有了age属性,则不做任何操作。
3:分析函数的声明,如果funcion foo(){},
3-1: 则把函数赋给AO.fooo,如果数据属性已经存在,则要被现在的新的值覆盖
下面开始分析上面修改1的执行的过程(自上崦下):
1、在window上面形成一个AO链,AO.name=undefine;
2、在函数的内部分析参数,函数没有参数,略过
3、在到变量声明阶段,在t函数的内部形成AO1,AO1.name=undfine;
4、分析函数声明,略过
执行过程:
1、首先是 在外层的AO.name=”test”
2、执行t函数,执行到console.log(name)时,函数内有name属性,就不会在到外面去寻找 执行输出undefine
3、执行赋值语句AO1.name=”test1”
4、输出当前的name值,”test1”;
这个问题解释清楚后,下面再分享几个代码:
function t(age) {
console.log(age);//1
var age = 99;
console.log(age);//2
function age() { }
console.log(age);//3
}
t(5);
这个问题看起来有点晕,但是事事都逃不过一个理,下面开始对这个进行词法分析
1-1、分析参数,有一个参数,形成一个AO.age=undefine;
1-2、接收参数AO.age=5;
2、分析变量声明,有一个var age,发现AO上面有一个AO.age,则不做任何处理
3、分析函数声明,有一个function age(){}声明, 则把原有的age覆盖成AO.age=function(){};
执行过程
1、执行第一个console.log(age)时,当前的AO.age是一个函数,所以输出的一个函数
2、这句var age=99;是对不AO.age的属性赋值,AO.age=99,所以在第二个输出的是99
3、同理第三个输出的是99,因为中间没有改变age值的语句了,
具体结果是,function age(){...},99,99,你算对了么?
如果把代码稍微再改下:
function t(age) {
var age;
console.log(age);
age = "99";
console.log(age);
function age() {
}
console.log(age);
}
t(5);
你发现这个和上面运行的结果一致,虽然js代码是从上到下到下执行的,但从这个例子可以看出,在执行前还有一定规则的“编译”。
好了,现在词法分析说的差不多了,万变不离其宗,下面开始再说几个容易混淆的问题:
对上面的代码再修改
1、
function t(age) {
var age;
console.log(age);
age = "99";
console.log(age);
function age() {
console.log(age);
}
age();//这里不一样
console.log(age);
}
t(5);
说明:这里的与前面的一样,但是这个唯一不同的是调用了age();呵呵,这个输出什么,这里的age根本不是一个函数了,所以肯定要报错了。不要被这个表现的现象忽悠了。
2、
function t(age) {
var age;
//age=99;这里被我注释掉了
console.log(age);
function age() {
console.log(age);
}
age();
console.log(age);
}
t(5);
现在想想答案会是什么?这里没有对age的赋值,说明age是一个函数,当这个函数执行的时候,age函数的内部没有age变量,根据作用域链到外层的函数去找,找到了一个age,但它还是一个函数,又再次输出函数,后面一个也是如此,所以结果是下面结果:
3、把函数声明函数变成用函数表达式
function t(age) {
// var age;
console.log(age);
var age=function () {
console.log(age);
}
age();
console.log(age);
}
t(5);
这个结果应该是?先说下函数的表达式,如果把表达式拆开也就明白了,拆成如下的结果:var age;age=function(){},也就是函数表达是其实是一个变量声明和赋值的过程,而不是一个真正的函数声明!所以有了前面的基础,这个输出就很简单了,答案是5,function(){},function(){};
4、把匿名函数转成“函数声明的形式”
function t(age) {
// var age;
console.log(age);
var age=function age () {
console.log(age);
}
age();
console.log(age);
}
t(5);
这个答案又是什么呢?是不是有点晕?这个结果和上面的结果是一个的,由这两个例子可以看出js的函数表达式只是一个赋值的过程。
好了说了这么多,今天的内容算是说完了, 希望能够让你从另一个全新的角度去考虑js的这门语言。后面会把js的原型链,js的继承链写出来,这三个链写完后,会把js中的this详细的总结下,js的部分有些“坑”说下,希望能够给你带来收获。
js高级知识---词法分析和AO 链的更多相关文章
- 第十九篇 js高级知识---词法分析和AO 链
上面一篇文章说了js的作用域链,这一节算是对上面的延申,有一个典型的例子,首先看原来的一段代码: var name = "test"; function t() { var b = ...
- JavaScript的高级知识---词法分析
JavaScript的高级知识---词法分析 词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 函数在运行的瞬间, ...
- 第20篇 js高级知识---深入原型链
前面把js作用域和词法分析都说了下,今天把原型链说下,写这个文章费了点时间,因为这个东西有点抽象,想用语言表达出来不是很容易,我想写的文章不是简单的是官方的API的copy,而是对自己的知识探索和总结 ...
- 第十八篇 js高级知识---作用域链
一直有想法去写写js方面的东西,我个人是最喜欢js这门语言,喜欢的他的自由和强大,虽然作为脚本语言有很多限制的地方,但也不失为一个好的语言,尤其是在H5出现之后.下面开始说说js的方面的东西,由于自己 ...
- js的高级知识---词法分析
词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 具体步骤如下: 函数在运行的瞬间,生成一个活动对象(Active ...
- python成长之路【第十六篇】:JavaScript的高级知识---词法分析
一.词法分析方法 js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 二.具体步骤如下: 函数在运行的瞬间,生成一个活动对象(Active O ...
- JS基础知识——原型与原型链
1.如何准确判断一个变量的数组类型 2.写一个原型链继承的例子 3.描述new一个对象的过程 4.zepto(或其他框架中如何使用原型链) 知识点: (1)构造函数 function Foo(name ...
- 从零开始学 Web 之 JS 高级(二)原型链,原型的继承
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- JS高级---一个神奇的原型链
一个神奇的原型链 <script> var divObj=document.getElementById("dv"); console.dir(divObj); //d ...
随机推荐
- Netstat 常用命令--备忘录
Netstat 用于显示与IP .TCP .UDP 和ICMP 协议相关的统计数据,一般用于检验本机各端口的网络连接情况. 常用参数 -a (all)显示所有选项,默认不显示LISTEN相关-t (t ...
- STL中的set使用方法详细!!!!
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- 基于C#的socket编程的TCP异步实现
一.摘要 本篇博文阐述基于TCP通信协议的异步实现. 二.实验平台 Visual Studio 2010 三.异步通信实现原理及常用方法 3.1 建立连接 在同步模式中,在服务器上使用Accept方法 ...
- WEB通知和React Native之即时通讯(iOS Android)
WEB通知和React Native之即时通讯(iOS Android) 一,需求分析 1.1,允许服务器主动发送信息给客户端,客户端能监听到并且能接收. 1.2,为了方便同一个系统内的用户可以指定某 ...
- System.Diagnostics.Process 测试案例
1.System.Diagnostics.Process 执行exe文件 创建项目,编译成功后,然后把要运行的exe文件拷贝到该项目的运行工作目录下即可,代码如下: using System; usi ...
- java进阶学习的一些思路
搞 Java 的年薪 40W 是什么水平? - 乔戈里的回答 - 知乎 https://www.zhihu.com/question/31437847/answer/566852748 在知乎上看了他 ...
- URL https://i.cnblogs.com/EditPosts.aspx?opt=1
URL url = new URL("https://i.cnblogs.com");URL url1 = new URL(url, "EditPosts.aspx?op ...
- Java instanceof运算符
java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. 用法: res ...
- 时间插件--daterangepicker使用和配置详解
1.序言: daterangepicker是Bootstrap的一个时间组件,使用很方便 用于选择日期范围的JavaScript组件. 设计用于Bootstrap CSS框架. 它最初是为了改善报表而 ...
- EntityFramework优化:查询性能
1. 禁用延迟加载 延迟加载是常见的方式,Entity Framework在需要时可以自动为一个实体的实例获取关联的数据. Entity Framework自动延迟加载需要同时满足以下3个条件: (1 ...