原文:JS的预编译和执行顺序 详析
最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题
代码:
复制代码
代码一
<head>
<title>事件处理</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<script type='text/javascript'>
//页面在在完成加载后
window.onload=function(){
var input=document.getElementById('button');
var p=document.getElementById('p');
var i=1;
while(input){
input.onclick=function(){
p.innerHTML+='<br />('+ i +') '+this.nodeName;
}
i++;
input=input.parentNode;
}
}
</script>
</head>
<body>
<div>
<input type='button' value='Event事件' id='button' />
<p id='p'>事件捕获的顺序:</p>
</div>
</body>
</html>
复制代码
显示的结果为:
当我更改了代码中红色的部分后得到的结果又不相同:
复制代码
代码二
<html>
<head>
<title>事件处理</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<script type='text/javascript'>
//页面在在完成加载后
window.onload=function(){
var input=document.getElementById('button');
var p=document.getElementById('p');
var i=1;
while(input){
input.onclick=function(){
p.innerHTML+='<br />('+ i++ +') '+this.nodeName;
}
input=input.parentNode;
}
}
</script>
</head>
<body>
<div>
<input type='button' value='Event事件' id='button' />
<p id='p'>事件捕获的顺序:</p>
</div>
</body>
</html>
复制代码
得到的结果为:
得出这两种不同的结果那是因为javascript代码在运行时有预编译和执行两个阶段,在预编译阶段会对函数和变量进行处理,对所有的声明变量会赋值为underfined,对所有的声明函数也会赋值为函数的定义。
下面我们来测试javascript的执行过程
1.javascript代码执行顺序时按照脚本标签<script>出现的顺序来确定的,浏览下面页面你会发现代码是按从上到下的顺序执行的
复制代码
<script type='text/javascript'>
alert('one');
</script>
<script type='text/javascript'>
alert('two');
</script>
<script type='text/javascript'>
alert('three');
</script>
复制代码
2. 因为变量在预编译时被赋予一个undefined初值,所以下面代码中,第一个变量name在代码中没有被赋值,所有就延用undefined这个值,下面的name被赋予了Jude,所以第二次输出的是Jude这个字符。
<script type='text/javascript'>
alert(name); //显示undefined
var name='Jude';
alert(name); //显示Jude
</script>
3.从如下结果中我们知道先是连续两次输出Hello Wrold!,最后连续两次输出test,得出这样的结果是因为javascript并非是完全按照顺序执行的,而是在执行之前先进行一个预编译,预编译 时声明式函数被提取出来,优先执行,而且相同的函数会进行覆盖,再执行赋值式函数。
复制代码
<script type='text/javascript'>
test(); //输出Hello World!
function test(){
alert('hello'); //声明式函数
}
test(); //输出Hello World!
var test=function(){ //赋值式函数
alert('test');
}
test(); //输出test
function test(){ //声明式函数
alert('Hello World!');
}
test(); //输出test
</script>
复制代码
4.下面代码显示显示hello,再显示hello world!,这是因为javascript中的给个代码块是相互独立的,当脚本遇到第一个<script>标签时,则javascript 解析器会等这个代码块加载完成后,先对它进行预编译,然后再执行之,然后javascript解析器准备解析下一个代码块,由于javascript是按 块执行的,所有一个javascript调用下一个块的函数或者变量时,会出现错误
复制代码
<script type='text/javascript'>
function test(){
alert('hello'); //显示hello
}
test()
</script>
<script type='text/javascript'>
function test(){
alert('hello world!'); //显示hello world!
}
test()
</script>
复制代码
5.虽然javascript是按块执行的,但不同的块却属于相同的全局作用域,不同的块的变量和函数式可以相互使用的,也就是某个块可以使用前面块的变量和函数,却不可以使用它之后的块的变量和函数
复制代码
<script type='text/javascript'>
alert(name); //显示undefined
var name='Jude';
function test(){
alert('hello');
}
fun(); //不能调用下一个块的函数
</script>
<script type='text/javascript'>
alert(name); //可以调用上一个块的变量,显示Jude
test(); //可以调用上一个块的函数,显示hello
function fun(){
alert('fun');
}
</script>
复制代码
6.javascript在预编译阶段是以函数来划分作用域的,然后再通过var 声明的变量来与声明函数开辟内存空间,对var变量赋初值undefined。在执行阶段再根据作用域来嘴变量进行赋值.
第一个代码块中函数里面的变量a是局部变量,因为a在函数内重新用var定义,所以输出undefined,而变量b是全局变量,因为在函数内没有用var重新声明b,所以在给变量b赋值时到全局变量中找全局变量b的值,所以输出的是b.
第二个代码块中的函数内都重新声明了变量a和b,所以他们都是函数内的局部变量,所以都输出undefined。
复制代码
<script type='text/javascript'>
var a='a';
var b='b';
function test(){
alert(a); //显示undefined
alert(b); //显示b
var a='test';
}
test();
</script>
<script type='text/javascript'>
var a='a';
var b='b';
function test(){
alert(a); //显示undefined
alert(b); //显示undefined
var a='test';
var b='test';
}
test();
</script>
复制代码
综上所述,javascript在执行时的步骤是:
1、先读入第一段代码块
2、对代码块进行语法分析,如果出现语法错误,直接执行第5步骤
3、对var变量和function定义的函数进行“预编译处理”(赋值式函数是不会进行预编译处理的)
4、执行代码块,有错则报错
5、如果还有下一段代码块,则读入下一段代码块,重复步骤2
6、结束
- JS的预编译和执行顺序 详析(及全局与局部变量)
最近在复习javascript的事件处理时发现了一个问题,于是总结一下:javascript的预编译和执行顺序的问题: <html> <head> <title> ...
- JS 的预编译和执行顺序
脚本执行js引擎做的工作: 语法分析 预编译 解释执行
- JS之预编译和执行顺序(全局和函数)
预编译的两种情况 全局: 1.全局 直接是script标签中的代码,不包括函数执行 执行前: 1.首先生成一个GO(global object)对象,看不到,但是可以模拟出来用来分析 2.分析变量声明 ...
- 关于JavaScript预编译和执行顺序以及函数引用类型的思考
昨晚在对项目中的一部分做模块化处理的时候,遇到了一个问题,一个重新定义的function对一个通用类中的function进行赋值覆盖的时候,失败了.问题抽象出来是这样的: <script > ...
- javascript的预编译和执行顺序
原文:javascript的预编译和执行顺序 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题 代码: 代码一<html> ...
- javascript运行机制之执行顺序详解(转)
转自http://www.admin10000.com/document/3385.html JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言, ...
- javascript 执行顺序详解
JavaScript是一种描述 型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行.如果你不能理解javaScript 语言的运行机制,或者简 ...
- javascript运行机制之执行顺序详解
1.代码块 指的的是有标签分割的代码段. 例如: <script type="text/javascript"> alert("这是代码块一"); ...
- JavaScript 运行机制之执行顺序详解
JavaScript是一种描述型脚本语言,它不同于 Java 或 C# 等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行.如果你不能理解 JavaScript 语言的运行机制 ...
随机推荐
- 写一方法用来计算1+2+3+...n,其中n作为参数输入,返回值可以由方法名返回,也可以由参数返回
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Linux 下github的使用
*初始化git仓库,使用git init命令 *添加文件到git仓库分两步: 1.使用git add filename :可分多次使用,添加多个文件到暂存区 2.使用git commit -m “ ...
- mvc导航配置
<?xml version="1.0" encoding="utf-8" ?><Configuration> <Navigatio ...
- 2015.7.17( NOI2015 day1 )
今天早起做了NOI2015网络同步赛.... 最近NOI是越来越向NOIP靠拢了....但是我还是不会做..... 第一题:程序自动分析 先离散化一下..然后最多就剩20w个数 , 不等于就存起来.. ...
- sencha touch(7)——list组件
1.list组件是一个很强大的组件.用于以一览表的形式或者列表的形式展示应用程序中的大量的数据.该组件使用XTemplate模版来显示数据,同时与数据仓库进行绑定.所以当数据仓库中的数据发生变化的时候 ...
- Linux下动态库使用
1. 静态库和动态库的基本概念 静态库,是在可执行程序连接时就已经加入到执行码中,在物理上成为执行程序的一部分:使用静态库编译的程序运行时无需该库文件支持,哪里都可以用, 但是生成的可执行文件较大.动 ...
- 给VS自动添加注释
找到类文件所在路径:C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplatesCache\CSharp\ ...
- SVN的trunk、branch、tag(二)
转——简单的对比 SVN的工作机制在某种程度上就像一颗正在生长的树: 一颗有树干和许多分支的树 分支从树干生长出来,并且细的分支从相对较粗的树干中长出 一棵树可以只有树干没有分支(但是这种情况不会持续 ...
- Java:利用java Timer类实现定时执行任务的功能
一.概述 在java中实现定时执行任务的功能,主要用到两个类,Timer和TimerTask类.其中Timer是用来在一个后台线程按指定的计划来执行指定的任务.TimerTask一个抽象类,它的子类代 ...
- JRE 和 JDK 的区别是什么?
JRE: Java Runtime Environment JDK:Java Development Kit JRE顾名思义是java运行时环境,包含了java虚拟机,java基础类库.是使用java ...