JS运行的三个步骤:

  1. 语法分析
  2. 预编译
  3. 解释执行

语法分析:通俗来说就是通篇检查你的代码有没有语法错误,有语法错误的话,程序是不会执行的

解释执行:也就是程序读一句执行一句

最重点的也就是预编译了,那么预编译到底是什么?它发什么在什么时候?

先来段代码压压惊

function fn (a) {
console.log(a)
var a = 123;
console.log(a)
function a () {}
console.log(a)
console.log(b);
var b = function () {}
console.log(b);
function d () {}
console.log(d)
}
fn(1)

这是打印结果

ƒ a() {}
123
123
undefined
ƒ () {}
ƒ d() {}

是不是有些地方有点懵逼和意外,其实这就是预编译捣的鬼,预编译就是在函数执行之前,在你的内存中申请一点空间,存放变量和函数
下面说说预编译到底是怎样的过程,也就是上面函数到底发生了什么

预编译过程:

  1. 创建AO对象(Active Object)
  2. 找形参和变量声明,将形参和变量声明作为AO对象的属性名,值为undefined
  3. 将实参与形参统一(把实参值赋予形参)
  4. 在函数体里找函数声明,把函数声明也作为AO对象的属性名,值为函数体()

上面那段代码,fn函数执行之前,先发生预编译过程

第一步

AO = { }

第二步

AO = {
a:undefined,
b:undefined
}

第三步

AO = {
a:1,
b:undefined
}

第四步

AO = {
a:function (){},
b:undefined,
d:function (){}
}

第四步代表预编译完成,然后函数执行

AO = {
a:123,
b:function (){},
d:function (){}
}
function fn (a) {
console.log(a) //这时函数未执行,打印function a(){}
var a = 123; //此时执行了a=123
console.log(a) //打印123
function a() {}
console.log(a) //打印123
console.log(b); //此时函数未执行,打印undefined
var b = function () {}
console.log(b); //此时执行了 b=function(){},打印function(){}
function d () {}
console.log(d) //打印function d(){}}
}
fn(1)

举几个‘栗子’

//1.
function fn(a,b) {
console.log(a); //打印1
c = 0;
var c;
console.log(b); //打印function b() {}
a = 3;
b = 2;
console.log(b); //打印2
function b() {};
function d() {};
console.log(b) //打印2
}
fn(1);
//2.
console.log(bar()); //打印function foo() { //body }
function bar(a,b) {
return foo;
foo = 10;
function foo(){
//body
}
var foo = 11;
}
//3.
console.log(bar()); //打印11
function bar(a,b) {
foo = 10;
function foo(){
//body
}
var foo = 11;
return foo;
}

以上是单个函数发生的预编译和函数执行过程,那么在<script></script>整个脚本中,是怎么样的呢?

<script type="text/javascript">
  var a = 1;
  function b () {
  var x = 3;
  function d () {}
  }
  var c = function () {
    var y = 4;
  }
</script>

同样的过程,在语法分析之后,开始预编译,不过此时预编译创建的叫GO对象,(Global Object)

GO/window = {
a:undefined,
c:undefined,
b:function b () {
var x = 3;
function d () {}
}
}

函数执行:

GO/window = {
a: 1,
c: function () { var y = 4; },
b: function b () {
var x = 3;
function d () {}
}
}

在执行b函数之前,将b函数预编译,也就是创建b函数的AO对象
如果有两个<script></script>呢?那就先执行完一个,再执行下一个。

注意问题:
预编译只有变量声明、函数声明,并不会发生赋值,赋值发生在执行阶段
匿名函数function (){ } 不参与预编译

JS运行三部曲(预编译)的更多相关文章

  1. js中的预编译

    预编译 js执行顺序: 词法/语法分析 预编译 解释执行 js中存在预编译 function demo() { console.log('I am demo'); } demo(); //I am d ...

  2. js - 基础 之 预编译总结

    js运行步骤 语法解析(检查有无语法错误) 预编译 解释运行(将 js 翻译成计算机识别的语言(0.1组成),翻译一行执行一行) 预编译 [全局]: 创建 GO( Grobal Object ) 对象 ...

  3. JS作用域和预编译(转载 学习中。。。)

    JS在页面加载过程中顺序执行.但是分块预编译.执行. JS在执行前会进行类似”预编译”的操作,而且先预声明变量再预定义函数. 此时注意,是声明,不是定义,如:var a = 1; 在预编译中,只是执行 ...

  4. js复习,预编译

    注意:函数声明整体提升.变量 声明提升 1.imply global 暗示全局变量:即任何变量,如果变量未声明就赋值,此变量就为全局对象所有 ==>  eg: a = 122;==>  e ...

  5. js三部曲---预编译

    函数内:1,创建AO对象//Activation Object 2,找函数内形参和变量声明,将其作为AO对象的属性名,值为undefined. 3,实参赋到AO对象 形参名里 4,在函数体里找函数声明 ...

  6. gulp最佳实践(包含js,css,html预编译,合并,压缩,浏览器自动刷新)

    gulp是基于流的自动化构建工具官方网址:http://www.gulpjs.com.cn/ 一.安装需要的模块 1.新建package.json,输入下面的内容 { "name" ...

  7. JS预编译详解

    我们都知道javascript是解释型语言,执行的特点呢是编译一行,执行一行.按照这个思路有时候我们在运行代码时会有一些令人费解的现象出现.下面我们一起来执行下面三段代码. <script> ...

  8. JS的预编译和执行顺序 详析(及全局与局部变量)

    最近在复习javascript的事件处理时发现了一个问题,于是总结一下:javascript的预编译和执行顺序的问题:   <html> <head> <title> ...

  9. JS的预编译和执行顺序 详析

    原文:JS的预编译和执行顺序 详析 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题   代码:   复制代码 代码一 <ht ...

随机推荐

  1. 如何从 100 亿 URL 中找出相同的 URL?

    题目描述 给定 a.b 两个文件,各存放 50 亿个 URL,每个 URL 各占 64B,内存限制是 4G.请找出 a.b 两个文件共同的 URL. 解答思路 每个 URL 占 64B,那么 50 亿 ...

  2. Linux基础命令---exportfs管理挂载的nfs文件系统

    exportfs exportfs主要用于管理当前NFS服务器的文件系统. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora. 1.语法        /usr/sb ...

  3. Spring Boot对日志的控制

    一.logback日志技术介绍 Spring Boot中使用的日志技术为logback.其与Log4J都出自同一人,性能要优于Log4J,是Log4J的替代者. 在Spring Boot中若要使用lo ...

  4. centos源码安装ruby

    目录 一.简介 二.程序部署 一.简介 Ruby,一种简单快捷的面向对象(面向对象程序设计)脚本语言.rvm是ruby的管理器,可以切换ruby版本,下载ruby. 二.程序部署 1.下载ruby w ...

  5. 手把手教你提交Jar包到Maven公共仓库 | 萌新写开源02

    在上一篇文章中,我介绍了自己的SpringBoot Starter项目,可以让我们使用注解的方式轻松地获取操作日志,并推送到指定数据源. 之前,我的项目开源在Github上,大家想要用我的项目,还得把 ...

  6. ES6解构赋值的简单使用

    相较于常规的赋值方式,解构赋值最主要的是'解构'两个字,在赋值的过程中要清晰的知道等号右边的结构. 先简单地看一下原来的赋值方式. var a=[1,2] 分析一下这句代码的几个点: (1)变量申明和 ...

  7. Blazor是春天还是寒风里的挣扎

    官方解释Blazor Blazor允许您使用c#而不是JavaScript构建交互式web UI. Blazor应用由可重用的web UI组件组成,这些组件使用c#.HTML和CSS实现.客户端和服务 ...

  8. pwnable_start

    第一次接触这种类型的题,例行检查一下 题目是32位 没有开启nx保护可以通过shellocode来获得shell 将题目让如ida中 由于第一次碰到这种题,所以我会介绍的详细一点, 可以看到程序中调用 ...

  9. Java网络多线程编程:对象流错误导致Connection reset

    Java网络多线程编程--对象流错误导致Connection reset 在老韩的网络多线程编程实战项目中,发生了如下报错: 服务器端和客户端均发生了报错,在确定相应对象流代码完全没有问题之后,回归定 ...

  10. java 多线程 集合的包装方法Collections.synchronizedXXXXX;线程安全的集合类:Java.util.concurrent.ConcurrentXXX;java.util.concurrent.CopyOnWriteXXXX

    问题:ArrayList  等线程不安全 当多线程并发修改一个集合数据时,可能同一个下标位置被覆盖. 示例代码: 一个List,我们创建10个线程,每个线程往这个List中添加1000条数据,结果往往 ...