js 运行代码的时候分为几个步骤:语法分析 ==》预编译  ==》解释执行

语法解析:通篇扫描代码,查看语法是否出错

解释执行读一行 - 解释一行 - 执行一行

预编译执行的操作:

// 假设之前并没有定义a
console.log(a);

打印结果:Uncaught ReferenceError: a is not defined

这个大家应该都知道:在变量未定义时就对变量进行访问就会报错(typeof 列外)

再看一个例子:

 // 假设之前并没有定义变量a
console.log(a); var a = 123; console.log(a);

看上面代码会打印什么?会不会报错?

打印结果:

undefined
123

为什么这个没有报错:因为在预编译的时候对变量进行了提升即变量提升。 定义的变量的声明(var a ;)被提到了代码块的最前面,变量的赋值操作(a = 123)没有变化。

所以被编译后就相当于

 // 假设之前没有定义变量a
var a; console.log(a); a = 123; console.log(a);

看下面这个例子:

 // 假设之前没有定义test
console.log(test); var test = 123; function test () { } console.log(test);

打印结果:

function test () {}
123

为什么第二行的输出的不是undefined 了?执行步骤是什么样子的?

因为函数声明在编译的时候也会进行提升,叫做函数提升

执行步骤:

1、变量提升:var test; 提升到最前面。此时test = undefined;

2、函数提升:function test () {}; 提升到最前面并覆盖var test; 的声明。所以第二行打印function test () {}; 此时test = function test () {}

3、进行赋值操作 test = 123; 此时test = 123;

 function test (test) {
console.log(test); // function test(){var a = 789}
var test = 123;
function test () {
var a = 789;
};
console.log(test) ; // 123
} test(456);

Why?

变量提升和函数提升是如何实现的?

预编译执行步骤

(a) 函数内

1、在代码定义之后执行之前生成活动对象AO(Activation Object ) 空对象{}

2、查找函数体内的形参和变量,定义为AO的属性,赋值为undefined;

3、将实参跟形参统一,即把实参赋值给AO[形参]

4、查找函数里的函数声明,将函数声明赋值给AO 即 AO[函数名] = 函数

(b) 全局

1、在代码定义之后执行之前生成全局环境对象GO(Global variable Object ) 空对象{}

2、查找变量,定义为GO的属性,赋值为undefined;

3、查找函数声明,将函数声明赋值给GO 即 GO[函数名] = 函数;

以上面的例子分析预编译过程:

function test (test) {
console.log(test); // function test(){var a = 789}
var test = 123;
function test () {
var a = 789;
};
console.log(test) ; // 123
} test(456); var a = 111; /** 全局 **/
// 第一步:创建GO
// GO{};
// 第二步:查找变量定义为GO的属性,赋值为undefined;
// GO{
// a: undefined
// };
// 第三步:将函数声明赋值给GO
// GO{
// a: undefined,
// test: function test(test) {...}
// } /** function test(test){...} 函数内 **/
// 第一步: 创建AO
// AO {}
// 第二步: 查找形参和变量,定义为AO的属性, 赋值为undefined;
// AO {
// test: undefined
// }
// 第三步: 形参和实参统一
// AO {
// test: 456
// }
// 第四步:将函数声明给AO
// AO {
// test: function test() { var a = 789 }
// }

之后就是一步一步的执行代码了

function test (test) {
console.log(test); // function test(){var a = 789}
var test = 123;
function test () {
var a = 789;
};
console.log(test) ; // 123
} test(456); var a = 111; // test(456); 进入到function test (test) {...} 内部
// console.log(test); // 打印 function test(){var a = 789}
// var test = 123; 由于 test 变量的声明已经提升,所以这句只执行 test = 123; 即AO[test] = 123
// AO {
// test: 123
// }
// function test() {var a = 789} 已经提升
// console.log(test) //打印 123
// 退出function test (test) {...} 销毁AO
// var a = 111; 由于 a 变量已经提升,这句只执行赋值 a = 111; 即 GO[a] = 111;
// GO{
// a: 111,
// test: function test(test) {...}
// } // 当页面销毁时销毁GO

js 预编译的更多相关文章

  1. js预编译

    先来做三个测试 eg1: var a; a = 1; function a() {}; console.log(a); eg2: var a; function a() {}; console.log ...

  2. Handlebars.js 预编译(转)

    Handlebars.js 官网上对预编译1是这样说的: 你需要安装 Node.js 你需要在全局环境中,通过 Npm 安装 handlebars 包 然后你就可以通过命令预编译你的 handleba ...

  3. 关于js预编译以及js文件执行顺序的几个问题。

    关于js的执行原理,除去html页面中直接添加的代码,js代码的放置可以分为两类. //情形a           <script type="text/javascript" ...

  4. JS预编译详解

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

  5. js预编译的四部曲

    众所周知javascript是解释性语言,主要特点为解释一行执行一行. 而在js运行时会进行三件事:1语法分析  2.预编译  3.解释执行 语法分析会在代码执行前对代码进行通篇检查,以排除一些低级错 ...

  6. js预编译和函数执行

    javascript 执行过程 1.语法检测(有没有基本的语法错误,例如中文,关键字错误...)2.词法分析(预编译) (1)创建全局GO(global object)对象 (2)对var声明的变量进 ...

  7. js预编译环节 变量声明提升 函数声明整体提升

    预编译四部曲 1.创建AO对象 2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined 3.将实参和形参统一 4.在函数体里面找函数声明,值赋予函数体 function fn(a) ...

  8. JS预编译过程

    GO和AO 变量的预编译 实例1 console.log(a); var a=1; console.log(a); 实际编译过程: 将a存入预编译对象中,赋值为undefined: 真正的赋值语句当程 ...

  9. Rails : css或js文件无法成功预编译或调用jquery类插件时预编译问题

    调用bootstrap css框架时,将bootstrap文件夹放入 vendor/assets/下 bootstrap文件结构如下:    [shenma@localhost demo]$ ls v ...

随机推荐

  1. RocketMQ 解决 No route info of this topic 异常步骤

    原文地址:https://blog.csdn.net/chenaima1314/article/details/79403113 rocketmq运行时提示 No route info of this ...

  2. Thematic002.字符串专题

    目录 Trie字典树 KMP AC自动机 Manacher 回文自动机 后缀数组 后缀自动机 Trie字典树 概念 我们先来看看什么是Trie字典树 可以发现,这棵树的每一条边都有一个字符 有一些点是 ...

  3. typescript step by step two

  4. GP工作室的项目计划书

    目录 零点六一八--项目计划书 一.团队简介 1.1团队名称:GP工作室(Gold Point Studio) 1.2团队成员 1.3成员简介 1.4团队特色 二.项目介绍 2.1项目名称: 零点六一 ...

  5. CentOS7.0+Hadoop2.7.2+Hbase1.2.1搭建教程

    1.软件版本 CentOS-7.0-1406-x86_64-DVD.iso jdk-7u80-linux-x64.tar.gz hadoop-2.7.2.tar.gz hbase-1.2.1-bin. ...

  6. 基于playcanvas的3d模型展示

    1.使用基于playcanvas的离线编辑器制作模型效果 2.使用基于playcanvas的开发包读取编辑好的3d模型进行在线3d展示 效果如下:

  7. 网络流(最大流-Dinic算法)

    摘自https://www.cnblogs.com/SYCstudio/p/7260613.html 网络流定义 在图论中,网络流(Network flow)是指在一个每条边都有容量(Capacity ...

  8. K8s下部署Istio

    一.环境准备 1.1环境信息 主机名 IP地址 用途 zhengzw-k8s-master 10.10.100.7 K8s Master zhengzw-k8s-node-1 10.10.100.15 ...

  9. BIO、NIO

    1. BIO和NIO 我们平常使用的IO是BIO(Blocking-IO),即阻塞IO.而NIO(No-blocking-IO)则是非阻塞IO,二者有什么区别呢? 预先知识准备 同步:发起调用后,调用 ...

  10. JavaScript所有函数和内置方法

    Number isFiniter() 检测传入的的数值是否在无穷大和无穷小之间(有限数字或者是可转换成有限数字)返回true,否则返回false.NaN返回false. isFinite(Number ...