一、先预处理后执行

在一个JavaScript文件或一个JavaScript代码块的内部,浏览器会先对代码进行预处理(编译),然后再执行。

预处理会跳过执行语句,只处理声明语句,同样也是按从上到下按顺序进行的。包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。 即使声明是在调用的下方进行的,但浏览器仍然先声明再调用(执行),这个现象叫做“提升”。所以,即便一个函数的声明在下方,在前面仍然可以正常执行这个函数。

注意1:对于声明并赋值的语句,例如 var a = 1,在预处理阶段会把这句话拆成两句:

var a;
a = 1;

也就是说,赋值或其他逻辑运算是在执行阶段进行的,在预处理阶段会被忽略。

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

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

二. 执行顺序

完成预处理之后,JavaScript代码会从上到下按顺序执行逻辑操作和函数的调用。

实例一:

首先我们来看两段简短的代码

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

  运行结果为:在这里打印出来的a都是1

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

  运行结果:在这里第一个a打印出来的结果是undefined,第二个是2

按照C/C++第个段代码输出的结果因该是1和2,为什么第一个a没法输出1呢?

分析原因:

1、在js语言中,没有类似于c语言这样的块级作用域。

2、js作用域链变量访问规则:

  (1)、当前作用域内存在要访问的变量时,则使用当前作用域中的变量。

  (2)、当前作用域中不存在要访问的变量时,则会到上一层作用域中寻找,直到全局作用域。

3、执行顺序:  

  (1)代码的检查装载阶段(预编译阶段),此阶段进行变量和函数的声明,但是不对变量进行赋值,变量的默认值为undefined。

  (2)代码的执行阶段,此阶段对变量进行赋值和函数的声明。

4、看上面的代码:第一个a输出undefined。原因:js作用域链的访问规则,当前作用域内存在要访问的变量a,所以使用当前作用域中的变量。再根据js代码的执行顺序,此时的a只是声明了而并未被赋值,默认为undefined,所以输出undefined。而第二个a,输出1,正是因为此时的a已经被声明且被赋值,所以a输出1。

在当前作用域内存在要访问的变量a,则就会使用当前作用域的变量a,只要当前作用域存在该变量即是对该变量进行了声明(即不会再用作用域外的值),直到var a=2;才是对该变量进行赋值。在代码中先是执行了console.log(a);在执行var a=2;所以此时a在该作用域内只是进行了声明还未进行赋值,所以就会输出undefined.

实例二:

例子1

var hello = function(){
  console.log('hello,zhangsan');
}
hello();
var hello = function(){
  console.log('hello,lisi');
}
hello();

  运行结果:

例子2

function hello(){
  console.log('hello,zhangsan');
}
hello();
function hello(){
  console.log('hello,lisi');
}
hello();

  

  运行结果:

JavaScript执行引擎并非一行一行地分析和执行程序,而是一段一段地分析执行的。而且在分析执行同一段代码中,定义式的函数语句会被提取出来优先执行。函数定义执行完后,才会按顺序执行其他代码。

问题:在例子2中,两次调用都会输出相同的内容“hello,lisi”。同样是声明两个相同名称的函数,为什么调用的结果却不一样呢?

这就是JavaScript执行顺序导致的。JavaScript执行引擎并非一行一行地分析和执行程序,而是一段一段地分析执行的。而且在分析执行同一段 代码中,定义式的函数语句会被提取出来优先执行。函数定义执行完后,才会按顺序执行其他代码。也就是说,在第一次调用hello函数之前,第一个函数语句 定义的代码已经被第二个函数定义语句的代码覆盖了,这就是为什么在例子2中第一次调用hallo时,也会输出后面定义的函数内容的原因了。

JavaScript 代码执行顺序的更多相关文章

  1. javaScript代码执行顺序

    javaScript是一种描述型脚本语言,由浏览器进行动态的解析和执行. 页面加载过程中,浏览器会对页面上载入的每个js代码块进行扫描. JavaScript是一段一段的分析执行的,在分析执行同一段代 ...

  2. javascript的执行顺序(转载)

    之前从JavaScript引擎的解析机制来探索JavaScript的工作原理,下面我们以更形象的示例来说明JavaScript代码在页面中的执行顺序.如果说,JavaScript引擎的工作机制比较深奥 ...

  3. 浏览器环境下JavaScript脚本加载与执行探析之代码执行顺序

    本文主要基于向HTML页面引入JavaScript的几种方式,分析HTML中JavaScript脚本的执行顺序问题 1. 关于JavaScript脚本执行的阻塞性 JavaScript在浏览器中被解析 ...

  4. 详解JavaScript的任务、微任务、队列以及代码执行顺序

    摘要: 理解JS的执行顺序. 作者:前端小智 原文:详解JavaScript的任务.微任务.队列以及代码执行顺序 思考下面 JavaScript 代码: console.log("scrip ...

  5. Java代码执行顺序(静态变量,非静态变量,静态代码块,代码块,构造函数)加载顺序

    //据说这是一道阿里巴巴面试题,先以这道题为例分析下 public class Text { public static int k = 0; public static Text t1 = new ...

  6. 当C#中带有return的TryCatch代码遇到Finally时代码执行顺序

    编写的代码最怕出现的情况是运行中有错误出现,但是无法定位错误代码位置.综合<C#4.0图解教程>,总结如下: TryCatchFinally用到的最多的是TryCatch,Catch可以把 ...

  7. final、static、代码块、静态代码块、内部类、代码执行顺序

    final final域使得确保初始化安全性(initialization safety)成为可能,初始化安全性让不可变形对象不需要同步就能自由地被访问和共享 作用在类上               ...

  8. [js]js代码执行顺序/全局&私有变量/作用域链/闭包

    js代码执行顺序/全局&私有变量/作用域链 <script> /* 浏览器提供全局作用域(js执行环境)(栈内存) --> 1,预解释(仅带var的可以): 声明+定义 1. ...

  9. 用 console.time()和 console.timeEnd() 测试你的 javascript 代码执行效率

    无意中学习到了一种测试 javascript 代码执行效率的一种方法,就记下来便于以后使用,用到了console对象中的  time  和  timeEnd  方法 . console.time('m ...

随机推荐

  1. report for PA2

    目录 说明 Report for PA 2(writed with vim) Part i - pa2.1 Steps: instr(seperately) Part ii - 2.2 Part ii ...

  2. 【Gradle】Android Gradle 多渠道构建

    Android Gradle 多渠道构建 多渠道构建的基本原理 在Android Gradle中,定义了一个叫Build Variant的概念,一个Build Variant=Build TYpe+P ...

  3. @supports特性查询

    特性查询也就是@supports规则,这个属性是作为CSS2.0扩展被引入的,是检测浏览器是否支持css属性值,是由逻辑与,逻辑或和逻辑非组合而成.主要的目的就是为了作者能够在不同的浏览器上根据不同的 ...

  4. Mac中 pip3 install mysqlclient 报错

    主要错误提示如下: ld: library not found for -lssl clang: error: linker command failed with exit code 1 (use ...

  5. Python语法速查: 12. 文件与输入输出

    返回目录 (1)文件基本操作 ● 文件常用操作 内置函数或方法 描述 open(name [,mode [,buffering]]) 内置函数.用来打开文件,返回一个文件对象(file对象).详见下述 ...

  6. reduce方法实现累加累乘的方式

    reduce函数对参数序列中的值进行积累,第二个参数可以为:str,tuple,list,代码示例如下: from functools import reduce#实现列表内的所有数的累加,即第一步x ...

  7. iconv转换

    /////////////////////////////////////////////////////// #include <iconv.h> #include <stdlib ...

  8. linux上安装jenkins过程

    最近在学到jenkins分布式构建时,需要一台部署jenkins的主机服务器master,自己用的win10作为slave,所以我想在虚拟机上先部署jenkins. centos还是ubuntu呢,算 ...

  9. qq cookie

    qq cookie from selenium import webdriver from selenium.webdriver import ActionChains import time, re ...

  10. nginx 反向代理之 proxy_pass

    格式很简单: proxy_pass URL; 其中URL包含:传输协议(http://, https://等).主机名(域名或者IP:PORT).uri. 示例如下: proxy_pass http: ...