先了解一下变量提升

console.log(a);
var a =1;

以上语句并不会报错,只是提示undefined。实际运行过程:

var a;
console.log(a);
a =1;

变量提升
JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting);

1.表示变量a已声明,但还未赋值。但是变量提升只对var命令声明的变量有效,如果一个变量不是用var命令声明的,就不会发生变量提升。

console.log(aa);
aa =1;

以上代码将会报错:ReferenceError: aa is not defined。
2. 与普通变量一样,js里的function也可看做变量,也存在变量提升情况:

a();function a(){console.log(1);
};

表面上,上面代码好像在声明之前就调用了函数a。但是实际上,由于“变量提升”,函数a定义部分被提升到了代码头部,也就是在调用之前已经声明了。但是,如果采用赋值语句定义函数,JavaScript就会报错:

a();var a = function(){console.log(1);
};// TypeError: a is not a function

因为,实际运行过程:

var a;
a();a = function(){console.log(1);
};

了解了变量提升,下面来看javascript执行顺序

对于一个HTML文档,浏览器的解析顺序为:按照文档流,从上到下逐步解析页面的结构。JavaScript代码作为通过标签嵌入或引入的脚本,也HTML文档的组成部分。因此,JavaScript代码在装载时的执行顺序也是根据脚本标签

但是,浏览器加载JavaScript时有个特点,那就是载入之后立即就会执行(先编译后执行),因为JavaScript可能会影响DOM树的结构,所以浏览器在执行完后才能继续加载下面的HTML内容。也就是说,浏览器下载并执行JavaScript的过程会阻塞DOM树的继续建立。所以,引入的多个js文件,会按顺序分开执行。同样的,对于不同

由于JavaScript通常需要操作DOM,所以,一般把JavaScript放在前或者文档结尾处引入。若需要在中引入,可以通过修改window.onload或者document.ready事件,强制等到DOM加载完成后再执行相关函数。

1.代码如下:

<scripttype="text/javascript">
functionHello() {
alert("Hello");
}
Hello();
functionHello() {
alert("Hello World");
}
Hello();
</script>

我们会看到这样的结果:连续输出了两次Hello World。
而非我们想象中的Hello和Hello World。
这是因为Javascript并非完全的按顺序解释执行,而是在解释之前会对Javascript进行一次“预编译”,在预编译的过程中,会把定义式的函数优先执行,也会把所有var变量创建,默认值为undefined,以提高程序的执行效率。
也就是说上面的一段代码其实被JS引擎预编译为这样的形式:

<scripttype="text/javascript">
var Hello = function() {
alert("Hello");
}
Hello = function() {alert("Hello World"); }
Hello();
Hello();
</script>

我们可以通过上面的代码很清晰地看到,其实函数也是数据,也是变量,我们也可以对“函数“进行赋值(重赋值)。
当然,我们为了防止这样的情况,也可以这样:

<scripttype="text/javascript">
function Hello() {
alert("Hello");
}
Hello();
</script>
<scripttype="text/javascript">
function Hello() {
alert("Hello World");
}
Hello();
</script>

这样,程序被分成了两段,JS引擎也就不会把他们放到一起了。
当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。
做如下处理:

  1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。
  2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = …这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined) 所以,就会出现当JavaScript解释器执行下面脚本时不会报错:
alert(a);                            // 返回值undefined
var a =1;alert(a);                            // 返回值1

由于变量声明是在预编译期被处理的,所以在执行期间对于所有代码来说,都是可见的。但是,你也会看到,执行上面代码,提示的值是undefined,而不是1。这是因为,变量初始化过程发生在执行期,而不是预编译期。在执行期,JavaScript解释器是按着代码先后顺序进行解析的,如果在前面代码行中没有为变量赋值,则JavaScript解释器会使用默认值undefined。由于在第二行中为变量a赋值了,所以在第三行代码中会提示变量a的值为1,而不是undefined。

同理,下面示例在函数声明前调用函数也是合法的,并能够被正确解析,所以返回值为1。

f();                                 // 调用函数,返回值1
function f(){return 1;}

但是,如果按下面方式定义函数,则JavaScript解释器会提示语法错误。

f();                                 // 调用函数,返回语法错误
var f = function(){alert(1);}

这是因为,上面示例中定义的函数仅作为值赋值给变量f,所以在预编译期,JavaScript解释器只能够为声明变量f进行处理,而对于变量f的值,只能等到执行期时按顺序进行赋值,自然就会出现语法错误,提示找不到对象f。

另外一些列子:

<script type="text/javascript">
/*在预编译过程中func是window环境下的活动对象中的一个属性,值是一个函数,覆盖了undefined值*/alert(func); //function func(){alert("hello!")}var func = "this is a variable"function func(){alert("hello!")}/*在执行过程中遇到了var重新赋值为"this is a variable"*/alert(func);  //this is a variable</script>
var name = "feng";
function func()
{
/*首先,在func环境内先把name赋值为undefined,然后在执行过程中先寻找func环境下的活动对象的name属性,此时之前已经预编译值为undefined,所以输出是undefined,而不是feng*/
alert(name);  //undefined
var name = "JSF";
alert(name);  //JSF
}
func();
alert(name);//feng
最后执行结果:  undefined ,  JSF,  feng

注意:(1)函数声明的提升优先于变量声明的提升;(2)重复的var声明会被忽略掉,但是重复的function声明会覆盖掉前面的声明。

在预处理阶段,声明的变量的初始值是undefined, 采用function声明的函数的初始内容就是函数体的内容。

javscript执行顺序(笔记)相关推荐

  1. MySQL 学习笔记(17)— SQL 执行顺序

    以查询语句为例,我们看下面的查询语句: (6)SELECT [DISTINCT | ALL] col1, col2, agg_func(col3) AS alias (1) FROM t1 JOIN ...

  2. java代码块执行顺序_Java笔记 | Java代码块执行顺序测试

    最近笔试常常遇到考察Java代码块执行顺序的题目,网上查看博客错漏百出,特地自己测试了一下. 如有错漏,希望路过的大佬指出来,以便我进行更改. 先上代码吧! public class ClassA { ...

  3. Java笔记——Java代码块的执行顺序

    Java代码块的执行顺序 Java程序中代码块的执行顺序对于学习Java的人来说是必不可少需要掌握的. 代码块 在Java中,使用{}括起来的代码被称为代码块. 根据其位置和声明的不同,可以分为: 局 ...

  4. 【笔记】Python 列表推导式(表达式 for 变量 in 列表 if 表达式 ) 执行顺序

    列表推导式用于使用其他列表创建一个新列表. 一般形式:中括号内含一个表达式,然后是一个for语句,然后是 0 个或多个 for 或者 if 语句. [表达式 for 变量 in 列表 if 表达式] ...

  5. sql笔记1:sql执行优先级和casewhen用法、sql执行顺序

    MySQL 语句中执行优先级--and比or高 例: select * from table where 条件1 AND 条件2 OR 条件3 等价于 select * from table wher ...

  6. 数据库笔记-sql执行顺序以及检索优先级

    sql 执行顺序优先级由高到低依次是: from 关键字后面的语句. where 关键字后面的语句." group by "后面的语句. select 后面的语句." o ...

  7. sql 执行顺序_10个简单步骤,完全理解SQL

    点击上方SQL数据库开发,关注获取SQL视频教程 SQL专栏 SQL数据库基础知识汇总 SQL数据库高级知识汇总 多年前收藏在笔记中的一篇文章,今天偶然翻出,重读了一遍,依然大有收获.分享出来,大家一 ...

  8. 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)

    今天无意中看到有关Invoke和BeginInvoke的一些资料,不太清楚它们之间的区别.所以花了点时间研究了下. 据msdn中介绍,它们最大的区别就是BeginInvoke属于异步执行的. Cont ...

  9. vue created 调用方法_vue 基础-生命周期 lifecycle 的执行顺序和作用

    前言 <vue 基础>系列是再次回炉 vue 记的笔记,除了官网那部分知识点外,还会加入自己的一些理解.(里面会有部分和官网相同的文案,有经验的同学择感兴趣的阅读) 平时开发中,我真的不太 ...

最新文章

  1. Rocksdb 的优秀代码(三)-- 工业级 线程池实现分享
  2. QCon讲师对对碰——洪小军采访梁宇鹏:就是爱Golang
  3. 【教程】2、读取新闻条目
  4. ES transport client批量导入
  5. 【拔刀吧少年】之shell数组
  6. 你必须掌握的20个python代码,短小精悍,用处无穷
  7. Android学习之碎片的生命周期
  8. 大屏设计-大数据综合展示可视化平台
  9. struts2默认action
  10. 第 8 章 crontab
  11. 生成验证码易语言代码
  12. 【PMP】三点估算结合正态分布图
  13. 虚拟机上安装openwrt并开发ipk包
  14. 你对软件测试了解多少?这篇文章会给你不一样的启示!
  15. 了解 React 之 Suspense 和 lazy
  16. 银联支付(网银h5)
  17. Excel隐身术了解一下,让自己的数据更安全
  18. 电脑文件怎么加密?第一种方法最简单
  19. matlab 简单算例,MATLAB 3D 动画简单实例 | 学步园
  20. NCN8025 TDA8035 智能卡接口IC读卡器芯片的替代解决方案

热门文章

  1. 【模板】【洛谷P5487】—Berlekamp-Massey算法
  2. 苹果iPhone 5C和5S发布后,消费者如何选择?
  3. RHEL / Rocky Linux 8 NetworkManager WWAN 获取 IPv6 失败的解决办法
  4. 今天学习VI编辑器的使用方法
  5. Web前端组态软件(可视化绘图编辑器)
  6. 云信小课堂 | Android 登录最佳实践
  7. Android Studio 显示gif动图的两种方式
  8. mysql err 1677
  9. 也来贴点儿轻松的吧,郭德纲语录
  10. 机器学习:决策树与随机森林