词法分析,按顺序分析 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)词法分析的更多相关文章

  1. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  2. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  3. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  4. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  5. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  6. 从头开始学JavaScript 笔记(一)——基础中的基础

    原文:从头开始学JavaScript 笔记(一)--基础中的基础 概要:javascript的组成. 各个组成部分的作用 . 一.javascript的组成   javascript   ECMASc ...

  7. 【原】javascript笔记之Array方法forEach&map&filter&some&every&reduce&reduceRight

    做前端有多年了,看过不少技术文章,学了新的技术,但更新迭代快的大前端,庞大的知识库,很多学过就忘记了,特别在项目紧急的条件下,哪怕心中隐隐约约有学过一个方法,但会下意识的使用旧的方法去解决,多年前ES ...

  8. JavaScript笔记目录

    JavaScript笔记目录 一.JavaScript简介 二.在HTML中使用JavaScript ...持续更新中,敬请期待

  9. 蛋糕仙人的javascript笔记

    蛋糕仙人的javascript笔记:https://www.w3cschool.cn/kesyi/kesyi-nqej24rv.html

  10. JavaScript笔记(第一章,第二章)

    JavaScript笔记(第一章,第二章) 第一章: <meta http-equiv="Content-Type" content="text/html; cha ...

随机推荐

  1. js iframe onload &line-height浏览器兼容问题

    1.IE iframe onload事件 在IE下给iframe添加onload事件经常无效,因为在IE下它最多只能被激活一次,而且无论你有多少个iframe,被激活的也只能是最后一个的.可以用下面的 ...

  2. ionic react-native和native开发移动app到底那个好

    ionic react-native和native开发移动app那个好 ? 移动端开发如何选型?这里介绍一下我眼中的ionic,react-native,native 三种移动端开发选型对比.欢迎大家 ...

  3. linux tricks 之 container_of.

    转载:http://blog.chinaunix.net/uid-20608849-id-3027972.html 由于内核中定义了很多复杂的数据结构,而它们的实例中的成员在作为函数参数传递的时,函数 ...

  4. Lucene实践

    Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能. OK,大家都知道这个是一个搜索检索工具,那究竟是怎么做检索的,其实道理是 ...

  5. GRE词汇3-4 +

    page3 accommodate: common commodity accompany: Accomplice:  com—共同 plic—重叠 Complicate duplicate repl ...

  6. Android APK反编译详解(附图)(转)

    这段时间在学Android应用开发,在想既然是用Java开发的应该很好反编译从而得到源代码吧,google了一下,确实很简单,以下是我的实践过程. 在此郑重声明,贴出来的目的不是为了去破解人家的软件, ...

  7. Codeforces Round #313 (Div. 2) D. Equivalent Strings

    D. Equivalent Strings Time Limit: 2 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/559/ ...

  8. AppInventor学习笔记(三)——油漆桶应用学习

    一.组件设置 1.画笔颜色选项 选取3个Button,然后改名为红.黄.绿三种颜色,然后进行相应属性的设置. 在这里有个问题就是如何放在一行.. 将3个按钮放进这个方框里面就可以变成一行了. 2.画布 ...

  9. android知识体系

    1.Android架构分为4层*应用程序层 Android会同一系列核心应用程序包一起发布,该应用程序包包括email客户端,SMS短消息程序,日历,地图,浏览器,联系人管理程序等.所有的应用程序都是 ...

  10. 简单几何(点与线段的位置) POJ 2318 TOYS && POJ 2398 Toy Storage

    题目传送门 题意:POJ 2318 有一个长方形,用线段划分若干区域,给若干个点,问每个区域点的分布情况 分析:点和线段的位置判断可以用叉积判断.给的线段是排好序的,但是点是无序的,所以可以用二分优化 ...