JAVASCRIPT之词法分析----你真的懂JS吗? 【未完待续】
2014-05-06 11:20
471 查看
先上几道题:
1、
2、
3、
4、
5、在不同浏览器上看看效果
谁能做到只分析代码就得出正确结论,并且说明原理, 那么恭喜你,说明你深刻掌握了词法分析的原理。
这五道题的结果可能让很多人感觉到意外,JS虽说是脚本语言, 但是它在执行之前会先做预解析, 也就是词法分析。
词法分析分成三个步骤:
1、检查var声明,
当一段程序或函数在运行前,会为当前作用域创建一个活动对象AO,
检查所有用var声明的变量, 将此变量挂到该AO上,但并不赋值(变量的赋值是发生在代码真正运行时);
2. 函数参数传递,
若这段程序是个函数,JS引擎会将传递的参数赋值给该函数的形参。
3、函数声明
检查当前域中的函数声明,将声明的函数挂到AO上。这样就可以形成一个AO链, 函数声明的形式为:function
aa(){} ,
现在我们再来分析这五道题 。
1, 第一道题中第1小题报错。因为使用了一个未声明的变量。第2小题为undefined,在词法分析中,当前活动对象已有变量a, 只是没有赋值。 所以为undefined.
2、 第二题是想判断a是否为window的属性, 如果是,则a=1, 可是JS引擎会先检查var声明,将a挂到AO上, 然后再运行。 导致代码在运行时, a已经声明, a=1.
3、 第三题当函数t在运行前, 词法分析先检查有没有var声明,没有, 再到参数传递, 将g挂到t的活动对象AO上,并将其赋值为2, 再去检查是否有函数声明, 正好有一个函数名为g的函数声明,先判断AO上是否有g这个变量,如果没有,则创建,没有则覆盖,那么g变成了一个函数。
值为function g(){ alert(1) };
4、第四题有点绕,需要我们了解作用域的概念, 让我们来一起分析下。 当代码在运行前, 首先在window上创建一个AO。将函数t挂到window的AO上。当代码调用函数t时,需要对函数t进行词法分析了,将传过来的参数function(){alert(t)} 传递给参数t,
那么alert(t)得到的结果自然是function(){alert(t)} ,可t()为何却得到
function t(t){
alert(t);
t();
}
匿名函数function () { alert(t); } 是在哪里定义的, 是在最外层的window上。 此匿名函数用到了变量t, 在该匿名函数中找不到变量t,那么就会往它的上一级去找。它的上一级是谁,
是window而不是运行时的t, window上正好有个变量为t.
如下图:
这个例子也正说明: 变量的值取决于声明时的环境而不是运行时的环境,这是与其它语言最大的不同。
如还不理解,可以再看看这题:
5、第五题,函数表达式
1、
<script> alert(a); </script>
<script> alert(a); var a = 1; </script>
2、
<script> if("a" in window){ var a = 1; } alert(a); </script>
3、
<script> function t(g){ alert(g); function g(){ alert(1); } } t(2); </script>
4、
<script> function t(t){ alert(t); t(); } t(function(){ alert(t); }); </script>
5、在不同浏览器上看看效果
<script> var t = function a(){ alert(a); } t(); alert(a); </script>
谁能做到只分析代码就得出正确结论,并且说明原理, 那么恭喜你,说明你深刻掌握了词法分析的原理。
这五道题的结果可能让很多人感觉到意外,JS虽说是脚本语言, 但是它在执行之前会先做预解析, 也就是词法分析。
词法分析分成三个步骤:
1、检查var声明,
当一段程序或函数在运行前,会为当前作用域创建一个活动对象AO,
检查所有用var声明的变量, 将此变量挂到该AO上,但并不赋值(变量的赋值是发生在代码真正运行时);
2. 函数参数传递,
若这段程序是个函数,JS引擎会将传递的参数赋值给该函数的形参。
3、函数声明
检查当前域中的函数声明,将声明的函数挂到AO上。这样就可以形成一个AO链, 函数声明的形式为:function
aa(){} ,
现在我们再来分析这五道题 。
1, 第一道题中第1小题报错。因为使用了一个未声明的变量。第2小题为undefined,在词法分析中,当前活动对象已有变量a, 只是没有赋值。 所以为undefined.
2、 第二题是想判断a是否为window的属性, 如果是,则a=1, 可是JS引擎会先检查var声明,将a挂到AO上, 然后再运行。 导致代码在运行时, a已经声明, a=1.
3、 第三题当函数t在运行前, 词法分析先检查有没有var声明,没有, 再到参数传递, 将g挂到t的活动对象AO上,并将其赋值为2, 再去检查是否有函数声明, 正好有一个函数名为g的函数声明,先判断AO上是否有g这个变量,如果没有,则创建,没有则覆盖,那么g变成了一个函数。
值为function g(){ alert(1) };
4、第四题有点绕,需要我们了解作用域的概念, 让我们来一起分析下。 当代码在运行前, 首先在window上创建一个AO。将函数t挂到window的AO上。当代码调用函数t时,需要对函数t进行词法分析了,将传过来的参数function(){alert(t)} 传递给参数t,
那么alert(t)得到的结果自然是function(){alert(t)} ,可t()为何却得到
function t(t){
alert(t);
t();
}
匿名函数function () { alert(t); } 是在哪里定义的, 是在最外层的window上。 此匿名函数用到了变量t, 在该匿名函数中找不到变量t,那么就会往它的上一级去找。它的上一级是谁,
是window而不是运行时的t, window上正好有个变量为t.
如下图:
这个例子也正说明: 变量的值取决于声明时的环境而不是运行时的环境,这是与其它语言最大的不同。
如还不理解,可以再看看这题:
<script> var a = 1; function t(g){ var a = 2; g(); } t(function(){ alert(a); }) </script>
5、第五题,函数表达式
相关文章推荐
- 使用 Node.js\/D8 分析 javascript 如何被 V8 引擎优化的
- 微软的JSMeter:一种新的方法分析和影响JavaScript性能
- [javascript]通过js获取cookie的实例及简单分析
- 使用 Node.js\/D8 分析 javascript 如何被 V8 引擎优化的
- 《JavaScript 源码分析》之 maxlength.js
- 韩顺平_轻松搞定网页设计(html+css+javascript)_第30讲_类和对象细节_创建对象的几种方式_js对象内存分析_学习笔记_源代码图解_PPT文档整理
- WebViewJavascriptBridge 分析oc向js发送消息处理流程
- js实例分析JavaScript中的事件委托和事件绑定
- 性能最高的javascript 发布订阅系统(pub/sub)Arbiter.js 源码分析
- 韩顺平_轻松搞定网页设计(html+css+javascript)_第26讲_js函数调用过程内存分析_js函数细节_学习笔记_源代码图解_PPT文档整理
- JS学习笔记 – 分析 JavaScript的执行顺序
- 《JavaScript 源码分析》之 jquery.unobtrusive-ajax.js
- 韩顺平 javascript教学视频_学习笔记9_js函数调用过程内存分析_js函数细节
- C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断
- Boba.js – 用于 Google 统计分析 JavaScript 库
- JS高级调试技巧:捕获和分析 JavaScript Error详解
- 韩顺平 javascript教学视频_学习笔记13_类和对象细节_创建对象的几种方式_js对象内存分析
- Js(JavaScript)中,弹出是或否的选择框示例(confirm用法的实例分析)
- 为什么没人推荐用 JavaScript/Node.js 做机器学习和数据分析- Quora
- js计算出现多位小数-Javascript 浮点运算问题分析与解决