Javascript的"预编译"思考
今天工作需要,搜索下JS面试题,看到一个题目,大约是这样的
- <script>
- var x = 1, y = z = 0;
- function add(n) {
- n = n+1;
- }
- y = add(x);
- function add(n) {
- n = n + 3;
- }
- z = add(x);
- </script>
问执行完毕后 x, y, z 的值分别是多少?
仔细看的人马上就知道了, x, y 和 z 分别是 1, undefined 和 undefined。
不过,如果将两个 add 函数修改一下,题目变为
- <script>
- var x = 1, y = z = 0;
- function add(n) {
- return n = n+1;
- }
- y = add(x);
- function add(n) {
- return n = n + 3;
- }
- z = add(x);
- </script>
那么这时 y 和 z 分别是什么呢?我马上想到是 2 和 4,不过结果却是 4 和 4。
这说明,在第一次调用 add 函数之前,第二个 add 函数已经覆盖了第一个 add 函数。原来,这是 JS 解释器的"预编译",JS 解析器在执行语句前会将函数声明和变量定义进行"预编译",而这个"预编译",并非一个页面一个页面地"预编译",而是一段一段地预编译,所谓的段就是一个 <script> 块。且看下面的代码
- <script>
- function add(n) {
- return n = n+1;
- }
- alert(add(1));
- </script>
- <script>
- function add(n) {
- return n = n+3;
- }
- alert(add(1));
- </script>
会分别弹出 2 和 4。
那么,将上面的题目再变换一下,如下
- <script>
- alert(typeof addA);
- addA();
- function addA() {
- alert("A executed!");
- };
- </script>
- <script>
- alert(typeof addB);
- addB();
- var addB = function() {
- alert("B executed!");
- };
- </script>
执行结果是什么呢? 按照前面的知识,第一个 <script> 块执行正常,结果就是弹出 "function" 和 "A executed!" 的对话框。
那么第二个 <script> 块呢? 执行结果是弹出 "undefined" 的对话框后报 JS 错误,说 addB 不是一个 function。
有点出乎意料?呵呵,其实第一个 script 块中的 addA 一句是函数声明,当然进行了"预编译",但是第二个 script 块中的 addB 一句并非函数声明。只不过在执行这段 <script> 之前对变量进行了"预声明",因此一开始变量addB是存在的,只不过是 undefined 的(可参看http://eclipse07.iteye.com/admin/blogs/484566)。因此执行结果便如上面所示。
将题目再变化下,如下
- <script>
- alert(typeof addB);
- addB();
- var addB = function addB() {
- alert("B executed!");
- };
- </script>
执行结果如何呢?
在 ff 下执行,与上面执行结果一样。打住,且在 IE6 下执行看看如何。
结果是弹出 "function" 和 "B executed!",一切正常。
Google 了一下,有人说这是 IE 的 BUG。
那么,请看下面的代码
- <script>
- alert(typeof addB);
- var addB = "variable";
- function addB() {
- alert("function addB");
- }
- alert(addB);
- </script>
执行结果是"function"和"variable"。
JS解析器先预定义了 addB 变量为 undefined, 但是 addB 函数覆盖了此变量,因此一开始执行结果是 function,然后 addB 被赋值为 "variable",因此最后执行结果是 "variable",上面的代码即使变为
- <script>
- alert(typeof addB);
- function addB() {
- alert("function addB");
- }
- var addB = "variable";
- alert(addB);
- </script>
结果也一样,这说明JS解析器先预声明变量,再预定义函数。
小结一下:JS 在执行前会进行类似"预编译"的操作,而且先预定义变量再预定义函数。
Javascript的"预编译"思考的更多相关文章
- 一步一步的理解javascript的预编译
首先,我们要知道javascript是单线程.解释性语言.所谓解释性语言,就是翻译一句执行一句.而不是通篇编译成一个文件再去执行. 其实这么说还没有这么直观,读一句执行一句那是到最后的事了.到JS执行 ...
- javascript的预编译和执行顺序
原文:javascript的预编译和执行顺序 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题 代码: 代码一<html> ...
- JavaScript的预编译和执行
JavaScript引擎,不是逐条解释执行javascript代码,而是按照代码块一段段解释执行.所谓代码块就是使用<script>标签分隔的代码段. 整个代码块共有两个阶段,预编译阶段和 ...
- 还原真实,javascript之预编译 / 预解析
今天在群里吹水时,有群友提出一个问题.我一看很简单,就立马给出了答案:因为存在变量提升,所以输出undefined.本以为无人反驳,可确招来口诛笔伐.作为写实派的我,一贯以来坚持真实是我的使命,岂能容 ...
- JavaScript 之 预编译 作用域,作用域链
第一次写博客,本来是学习jQuery遇到闭包问题,发现并没有理解闭包,发现闭包牵扯的知识点太多.复习了一遍(发现自己该记住的全忘了)写在博客里,自己也是小白,希望大神们指点迷津,必将感激不尽. 我们知 ...
- JavaScript之预编译
javascript是一种解释性弱类型语言,在浏览器中执行时,浏览器会先预览某段代码进行语法分析,检查语法的正确与否,然后再进行预编译,到最后才会从上往下一句一句开始执行这段代码,简单得来说可以表示为 ...
- JavaScript函数——预编译
四部曲 创建AO对象 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined. 将实参值和形参值统一 在函数体内找函数声明,值赋予函数体. 权重按顺序依次增加.以下例子即可体现上述规则 ...
- javascript预编译和执行过程总结
javascript相对于其它语言来说是一种弱类型的语言,在其它如java语言中,程序的执行需要有编译的阶段,而在javascript中也有类似的“预编译阶段”(javascript的预编译是以代码块 ...
- javaScript 预编译过程浅尝
javaScript 预编译过程 1.创建AO对象(Activation Object) AO{ a: } 2.找形参和变量声明,将变量和形参作为AO属性名,值为undefined AO{ a:und ...
随机推荐
- ios runtime的相关知识
一.iOS runtime原理 对于runtime机制,在网上找到的资料大概就是怎么去用这些东西,以及查看runtime.h头文件中的实现,当然这确实是一种很好的学习方法,但是,其实我们还是不会知道r ...
- 键盘unicode值对照表
A:65 B:66 C:67 D:68 E:69 F:70 G:71 H:72 I:73 J:74 K:75 L:76 M:77 N:78 O:79 P:80 Q:81 R:82 S:83 T:84 ...
- sqlserver2008创建数据库 报 Cannot read property is filestream 此属性不可用于sql server 7.0 解决
在创建数据库的时候,报整个错误 Cannot read property is filestream 此属性不可用于sql server 7.0 按照网上的方法 (http://blog.csdn. ...
- CA*Layer(CAShapeLayer--CATextLayer)
CAShapeLayer CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类.你指定诸如颜色和线宽等属性,用CGPath来定义想要绘制的图 形,最后CAShapeLayer就 ...
- python_way day12 sqlalchemy,原生mysql命令
python_way day12 sqlalchemy,mysql原生命令 1.sqlalchemy 2.mysql 原生命令 一,sqlalchemy SQLAlchemy本身无法操作数据库,其必 ...
- 2dx中文乱码问题
我们的代码里面有一个bug 为了跟之前兼容的策划导表工具兼容 导表工具导出的excel全部都是ansi的 为了兼容就只能手动改成utf 8 无bom格式 后来策划嫌烦了 就让在程序段处理这个 研究了好 ...
- PL/SQL 听课笔记
PL/SQL: 知识回顾: SQL: 结构化查询语言: T-SQL: microsoft sql语言: PL/SQL: Oracle sql语言: 变量命名规则: 1.首字母必须是字母,可以包含字 ...
- iOS常用define宏定义
1. 屏幕宽高及常用尺寸 #define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)#define SCREEN_HEIGHT ([U ...
- iOS进阶收藏
XCode自带重构方式http://www.cocoachina.com/ios/20160127/15097.html iOS迭代多语言开发http://www.cocoachina.com/ios ...
- Joke
你忍心蜗居在不到10平米的小屋里吗?你忍心看着自己的女友和你奋斗一辈子还供不起一套房吗?你忍心看着你父母缩衣节食把仅有的一点养老金帮你还房贷吗? 这里才是实现你梦想的地方.加入我们,待遇从优,装备齐全 ...