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. [bzoj4417] [洛谷P3990] [Shoi2013] 超级跳马

    Description 现有一个n行m列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘.例如,当n = 3, m = 10时,下图是一种可 ...

  2. A complex 16-Level XSS Challenge

    A complex 16-Level XSS Challenge, held in summer 2014 (+1 Hidden Level) Index Level 0 Level 1 Level ...

  3. 建立MVC的依赖项注入 Setting up MVC Dependency Injection 精通ASP-NET-MVC-5-弗瑞曼

    The result of the three steps I showed you in the previous section is that the knowledge about the i ...

  4. Mysql梳理-关于索引/引擎与锁

    前言 最近突发新型肺炎,本来只有七天的春节假期也因为各种封锁延长到了正月十五,在家实在闲的蛋疼便重新研究了一下Mysql数据库的相关知识,特此总结梳理一下.本文主要围绕以下几点进行: 1.Mysql的 ...

  5. STM8L15X 硬件I2C调试总结

    最近接到一个项目需要使用STM8L上硬件I2C与SN3731通信,用户方是个方案商,硬件设计人员也没留测试点,直接就把板子焊了拿来了.调试时除了swio口能用所有都不能用,硬件设计大概是为了显得自己焊 ...

  6. SpringBoot 的不同

    这些在写前端页面的时候,ssm框架中,在页面做出修改之后,保存一下,重新刷新一下浏览器页面就发生了更新 但是sprigBoot中好像不一样,好像是需要对页面进行重新编译一下,浏览器页面才会发生变化 ( ...

  7. SpringBoot任务篇Ⅴ --- 异步任务、定时任务、邮件任务

    Java的任务在项目中需要用到的地方很多,比如,每月月末的财务报表给财务部门,定时给领导发个邮件短信等等.这时候我们就需要用到任务了,任务调度本身涉及到多线程并发.运行时间规则制定和解析.场景保持与恢 ...

  8. js实现表单的提交

    <form action="" method="post" name="form"> <tr>           ...

  9. tmobst6

    1.(单选题)Oracle数据库中,在SQL语句中连接字符串的方法是:(). A)CAT B)CONCAT C)JOIN D)UNION 2.(单选题)在数据库中,有一个名为seq的序列对象,以下语句 ...

  10. shell命令之一天一见:grep

    一. 简介 grep (缩写来自Globally search a Regular Expression and Print)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来 ...