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. 【数据结构】FHQ Treap详解

    FHQ Treap是什么? FHQ Treap,又名无旋Treap,是一种不需要旋转的平衡树,是范浩强基于Treap发明的.FHQ Treap具有代码短,易理解,速度快的优点.(当然跟红黑树比一下就是 ...

  2. Quartz cron 表达式(linux 定时器,java 定时任务,spring task定时任务)

    原文地址:https://blog.csdn.net/feng27156/article/details/39293403 Quartz cron 表达式的格式十分类似于 UNIX cron 格式,但 ...

  3. Frameworks.Entity.Core 1

    CommonEnums 1系统模块BlockType 2证件类型IDType 3在线支付类型OnLineType 4操作权限,支持位移运算OperatorAuthority 5订单状态: 1000-待 ...

  4. libc.so.6修改链接指向后导致系统无法使用的原因及解决方法

    https://www.cnblogs.com/weijing24/p/5890031.html http://man.linuxde.net/ldconfig

  5. 工具之sort

    转自:http://www.cnblogs.com/dong008259/archive/2011/12/08/2281214.html sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参 ...

  6. rabbitmq使用总结

    rabbitmq 架构图 RabbitMQ 中的 broker 是指什么?cluster 又是指什么 broker 是指一个或多个 erlang node 的逻辑分组,且 node 上运行着 Rabb ...

  7. spring cloud oauth2搭建认证中心与资源中心

    一 认证中心搭建 添加依赖,如果使用spring cloud的话,不管哪个服务都只需要这一个封装好的依赖即可 <dependency> <groupId>org.springf ...

  8. 类与 Object 的应用

    # 类与 Object 的应用 + 面试题 类介绍 Java 程序是由若干个类组成的,类也是面向对象编程思想的具体实现. 以下为类的基本使用: public class Cat { // 私有属性 p ...

  9. kubernetes容器端口设置的坑

    1.使用dockerhub上面的镜像的时候,先到dockerhub上看镜像的相关信息. 2.不能随便修改容器应用的镜像,会出问题.

  10. 在sublime text 3中搭建Java开发环境

    在jdk bin目录下新建一个bat文件: 如D:\JAVA\jdk1.8.0_65\bin\runJava.bat @ECHO OFF cd %~dp1 ECHO Compiling %~nx1.. ...