Javascript 笔记与总结(1-2)词法分析
词法分析,按顺序分析 3 样:
第 1 步:先分析参数
第 2 步:再分析变量声明
第 3 步:再分析函数声明
一个函数能使用的局部变量,就从上面 3 步分析而来。
具体步骤:
0:函数运行前的瞬间,生成 Active Object(活动对象)
1: 1.1 把函数声明的参数,形成 AO (Active Object)的属性,值全是 undefined,
1.2 接受实参形成 AO 相应属性的值
2:分析变量声明,如 var age,如果 AO 上已经有 age 属性,则不作任何影响;如果 AO 上还没有 age 属性,则添加 AO 属性,但此时没赋值,值是 undefined
3:分析函数声明,如 function foo(){},则把函数赋给 AO.foo 属性
注:如果此前 foo 属性已经存在,则会被覆盖成函数
例1
<script>
function a(b){
alert(b);
function b(){
alert(b);
}
b();
}
a(1);
</script>
【答案】:两次弹出
function b(){
alert(b);
}
【分析】
分析期:
0. AO = {}
1.
1.1 分析参数 AO = {b:undefined}
1.2 接收参数 AO = {b:1}
2. 分析 var 声明,此处函数没有 var
3. 分析函数声明,AO = {b:function(){alert(b);}}
执行期:
alert(b); // function
b(); // 由作用域寻找到 a 函数中的 b,即 function,alert() 出来
例2
<script>
function t(age){
alert(age);
}
t(5); //
t(); //undefined
</script>
【分析】
词法分析过程:
AO{ age = undefined }
运行过程:
t(5); → AO.age = 5; alert(AO.age); //5
t(); → AO.age = undefined; //AO.age 没有得到赋值,还是 undefined
例3
<script>
function t(age){
var age = 10;
alert(age);
}
t(5);
</script>
弹出 10。
【分析】
词法分析过程:
0. 形成AO = {}
1.
1.1 分析形参 AO = {age:undefined}
1.2 接收形参:AO = {age:5}
2. 分析 var age,发现 AO 已有 age 属性,不做任何影响
执行过程:
AO.age = 10
alert(age); //10
例4(和例1 做对比):
<script>
function t(greet){
var greet = 'hello';
alert(greet);
function greet(){
}
alert(greet);
}
t(null);
</script>
弹出两次 'hello'
【分析】
词法分析过程:
0. AO = {}
1.
1.1 分析形参:AO = {greet = undefined}
1.2 接收形参:AO = {greet:null}
2. 分析 greet 变量声明,AO 已经有 greet 属性,因此不做任何影响
3. 分析 greet 函数声明,AO.greet = function(){},被覆盖成函数
执行过程:
greet = 'hello';
alert(greet);
alert(greet);
【再分析】
var greet = 'hello';
这一句要当成两句看(两次执行):① 分析期的 var 声明过程 ② 运行期的 赋值 过程
由于在运行期被赋值成了 'hello',因此两次 alert 弹出的都是 'hello'
如果去掉该句(则和例 1 一样)或者改为 var greet; ,则弹出两次
function greet(){}
例5
<script>
function a(b){
alert(b);
b = function (){
alert(b);
}
b();
}
a(1);
</script>
分别弹出 1 和 function (){alert(b)}
【词法分析过程】:
0:AO = {}
1.分析参数 AO = {b:undefined} → {b:1}
2.分析 var 声明,没有
3.分析函数声明,没有
注:b = function(){alert(b)} ,是一个赋值过程,在执行器才起作用
【执行过程】:
alert(b); //b = 1
b = function(){
alert(b); //往上找,找到b = function(){}
}
b(); // funtion
【函数声明 与 函数表达式】:
函数可以赋值给变量,可以作为参数来传递
function t1(){
}
和
t2 = function(){
}
t1 是函数声明,虽然全局内也得到一个 t1 变量,值是 function;
t2 只是一个赋值过程,值是右侧的表达式的返回结果,即函数
因此 t1 和 t2 两种方式在词法分析时,有着本质区别:前者在词法分析阶段就发挥作用,后者在函数运行阶段才发挥作用
例如:
(function(window,undefined){
})(window)
这是 jQuery 的最外层代码
【分析】
(function(window,undefined){})
这是内层表达式,返回值是函数,包在小括号里,当成表达式来执行
(function(window,undefined){})(window)
立即调用
而内层函数又没有起名字,成为匿名函数
这种手法,匿名函数,立即执行,不污染全局,称为 立即执行匿名函数表达式
传 window 是为了速度,不传 undefined 是为了防止外界对 undefined 的污染(在 IE 、FF 低版本中,undefined 可以重新赋值,例如 undefined = 3;)
【作用域链】
指函数由内到外,产生的 AO 链
词法分析时由外至内,分析 AO 链;执行时由内到外,寻找 AO 链
更多词法作用域文章:JavaScript的词法作用域
Javascript 笔记与总结(1-2)词法分析的更多相关文章
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第3章:使用函数--个人总结
前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- 从头开始学JavaScript 笔记(一)——基础中的基础
原文:从头开始学JavaScript 笔记(一)--基础中的基础 概要:javascript的组成. 各个组成部分的作用 . 一.javascript的组成 javascript ECMASc ...
- 【原】javascript笔记之Array方法forEach&map&filter&some&every&reduce&reduceRight
做前端有多年了,看过不少技术文章,学了新的技术,但更新迭代快的大前端,庞大的知识库,很多学过就忘记了,特别在项目紧急的条件下,哪怕心中隐隐约约有学过一个方法,但会下意识的使用旧的方法去解决,多年前ES ...
- JavaScript笔记目录
JavaScript笔记目录 一.JavaScript简介 二.在HTML中使用JavaScript ...持续更新中,敬请期待
- 蛋糕仙人的javascript笔记
蛋糕仙人的javascript笔记:https://www.w3cschool.cn/kesyi/kesyi-nqej24rv.html
- JavaScript笔记(第一章,第二章)
JavaScript笔记(第一章,第二章) 第一章: <meta http-equiv="Content-Type" content="text/html; cha ...
随机推荐
- Linux用户名显示-bash-4.1$快速排查
最近项目使用的的服务器有点多(100多台),很多开发同事经常问这个问题,现在整理如下: 几个可能导致的原因: 1 用户的家目录所属组被改为root,解决方法使用root执行cd /home/;chow ...
- 配置无线网络的时候会提示“Enter Password for Default Keyring to Unlock”
密钥管理软件Seahorse有关,这个时候我们打开c配置一下就可以解决. 命令行下运行seahorse或依次点击菜单“应用程序→附件→密码和加密密钥”, 在login一行中右键选择更改密码,然后什么都 ...
- Linux下可以替代windows的软件汇总:(不断完善中)
http://www.ubuntukylin.com/ukylin/forum.php?mod=viewthread&tid=9530 原则:不求全面,只求实用.主要针对桌面级应用.网购: ...
- js checkbox
js checkbox <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...
- MySQL支持的列类型
MySQL支持大量的列类型,它可以被分为3类:数字类型.日期和时间类型以及字符串(字符)类型.本节首先给出可用类型的一个概述,并且总结每个列类型的存储需求,然后提供每个类中的类型性质的更详细的描述. ...
- mysql中char与varchar的区别分析(补充一句,int和integer没区别)
转自:http://www.jb51.net/article/23575.htm 在mysql教程中char与varchar的区别呢,都是用来存储字符串的,只是他们的保存方式不一样罢了,char有固定 ...
- BZOJ 3224: Tyvj 1728 普通平衡树 treap
3224: Tyvj 1728 普通平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除 ...
- 输入框提示文字js
<input style="margin-right: 0px; padding-right: 0px;" class="text" required=& ...
- Android 滑动冲突处理
要想解决滑动冲突就必须好好理解 Android 的事件分发机制.不了解 Android 事件分发机制的请先参考资料学习一下. 一般有 2 种方法 1 外部拦截法 这个非常简单,因为事件是从父 view ...
- BZOJ3075 : [Usaco2013]Necklace
首先对b串做kmp求出nxt数组. 设f[i][j]表示考虑了a的前i个字符,在b中匹配到了j的最长长度,按照kmp算法直接转移即可. $ans=n-\max(f[n][j])$. 时间复杂度$O(n ...