JS----预编译及变量提升详解
前言
JS属于解释型语言,在执行过程中顺序执行,但是会分块先预编译然后才执行。因此在JS中存在一种变量提升的现象。搞懂预编译环节,变量提升自然而然也就懂了。本文讲围绕以下几点进行介绍(变量提升会穿插在其中讲解):
- 预编译执行步骤
- 示例演示
预编译执行步骤
预编译发生在函数执行的前一刻,过程如下:
- 创建AO对象,执行期上下文(后面更新关于执行期上下文详解)。
- 寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined.
- 将形参和实参相统一,即更改形参后的undefined为具体的形参值。
- 寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。
至此,预编译环节结束,函数中咯变量按照最终AO对象中的值开始执行。接下来,结合示例演示就会更加清晰。
示例演示
我们先来看下面这段代码:
function fn(a){console.log(a);var a = 123;console.log(a);function a(){};console.log(a);var b = function(){};console.log(b);function d(){};}//调用函数fn(1);
复制代码
接下来我们来按照前面的步骤详细分析它的预编译执行过程:
- 创建AO对象
AO{//空对象
}
复制代码
- 找形参和变量声明
AO{a : undefined,b : undefined
}
复制代码
- 形参和实参相统一
AO{a : 1,b : function(){}
}
复制代码
- 找函数声明
AO{a : function a(){},b : undefined,d : function d(){}
}
复制代码
预编译环节就此结束,此时的AO对象已经更新为:
AO{a : function a(){},b : undefined,d : function d(){}
}
复制代码
函数开始逐行顺序执行:
function fn(a){console.log(a);// 输出functiona(){}var a = 123;//执行到这里重新对a赋,AO对象再一次更新console.log(a);// 输出123function a(){};//预编译环节已经进行了变量提升,故执行时不在看这行代码console.log(a);// 输出123var b = function(){};//这个是函数表达式不是函数声明,故不能提升,会对AO中的b重新赋值console.log(b);//输出function(){}function d(){};}
复制代码
至此,函数执行完毕,销毁AO对象。
我们再来看几个例子,熟悉函数的预编译过程。
示例一:
function test (a,b){console.log(a);c = 0;var c;a = 3;b = 2;console.log(b);function b(){};function d(){};console.log(b);
}
//调用函数
test(1);
复制代码
它的AO创建过程如下(此处省略创建空AO对象的部分,下文同):
AO1{a : undefined,b : undefined,c : undefined
}AO2{a : 1,b : undefined,c : undefined
}AO3{a : 1,b : function b(){},c : undefined,d : function d(){}
}
复制代码
至此预编译环节完成,开始执行:
function test (a,b){console.log(a); //输出1c = 0; //给AO对象中的c重新赋值0var c;//预编译环节变量提升,不再读此行代码a = 3;//给AO对象中的a重新赋值3b = 2;//给AO对象中的b重新赋值2console.log(b);//输出2function b(){};//预编译环节变量提升,执行时不再读这行代码function d(){};//预编译环节变量提升,执行时不再读这行代码console.log(b);//输出2
}
//调用函数
test(1);
复制代码
示例二:
这个例子中我们引入全局对象GO。GO与AO的过程类似
function test(){var a = b = 123;
}
test();
复制代码
此函数的执行过程:先把123赋给b,再声明a,再把b赋给a。此时变量b未经声明就赋值,为全局变量。预编译环节如下:
GO1{b : undefined
}
AO1{a : undefined
}GO2{b : 123;
}
AO2{a : 123;
}
复制代码
示例三 :
console.log(test);
function test(test){console.log(test);var test = 234;console.log(test);function test(){};
}
test(1);
var test = 123;
复制代码
我们来看它的预编译过程:
//执行前(页面加载完成时)生成GO对象
GO1{test : undefined
}
GO2{test : function(){}
}//输出 function test(){...}//执行test()前生成它的AO对象
AO1{test : undefined
}
AO2{test : 1
}
AO3{test : function test(){}
}//预编译结束开始执行test(1);
AO4{test : 234
}
//输出234
复制代码
示例四:
function demo(){console.log(b);if(a){var b = 100;}console.log(b);c = 234;console.log(c);
}
var a;
demo();
a = 10;
console.log(c);
复制代码
我们来看它的预编译过程:
//首先是全局对象GO
GO1{a : undefined
}
G02{a : undefined,demo : function demo(){}
}
//执行demo()前预编译,由于demo中的c未声明就使用故为全局对象//输出undefined
GO3{a : undefined,demo : function demo(){}c : undefined
}
//此时a还是undefined,故不执行if()代码块
//输出还是undefined
GO4{a : undefined,demo : function demo(){}c : 234;
}
//输出234
GO5{a : 10,demo : function demo(){}c : 234;
}
//输出234
复制代码
JS----预编译及变量提升详解相关推荐
- JS ES6中export和import详解
1.Export 模块是独立的文件,该文件内部的所有的变量外部都无法获取.如果希望获取某个变量,必须通过export输出, // profile.js export var firstName = ' ...
- AO是什么?GO是什么?深度解析JS预编译遇见AO和GO
写在前面 三月结束了,四月开始了.希望这个世界早点好起来. 今天是个好日子,好呀嘛好日子.哈哈哈哈哈哈,省里发文件了,终于让我看到了开学的希望,心情格外的舒适. 好了好了,来说说今天都干嘛了吧.今天又 ...
- 3种Javascript图片预加载的方法详解
3种Javascript图片预加载的方法详解 预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度. 这对图片画廊及图片占据很大比例 ...
- js高级第一章--变量提升,函数提升
js高级第一章–变量提升,函数提升 文章目录 前言 一.什么是js里的提升? 二.js变量提升 三.js函数提升 四.特殊情况 总结 前言 在js中,最基本的声明方式有三种,即:var,let,con ...
- 使用VS2010编译MongoDB C++驱动详解
最近为了解决IM消息记录的高速度写入.多文档类型支持的需求,决定使用MongoDB来解决. 考虑到MongoDB对VS版本要求较高,与我现有的VS版本不兼容,在leveldb.ssdb.redis.h ...
- 【转】Android APK反编译就这么简单 详解(附图)
转自:http://blog.csdn.net/vipzjyno1/article/details/21039349/ [置顶] Android APK反编译就这么简单 详解(附图) 分类: and ...
- Nginx内置变量以及日志格式变量参数详解
Nginx内置变量以及日志格式变量参数详解 $args #请求中的参数值 $query_string #同 $args $arg_NAME #GET请求中NAME的值 $is_args #如果请求中有 ...
- js 预编译 解释执行 作用域链 闭包
<script>var a,b = 1;function c(x){var aa = 2;function d(){var ab = 3;}}var d = function(){//.. ...
- ThinkPHP模版引擎之变量输出详解
ThinkPHP模版引擎之变量输出详解 使用ThinkPHP开发有一定时间了,今日对ThinkPHP的模板引擎变量解析深入了解了一下,做出一些总结,分享给大家供大家参考.具体分析如下: 我们已经知道了 ...
最新文章
- OpenDesktop 1.0开放桌面操作系统光盘启动安装过程详细图解
- [Win] 利用Memory DC抽取EXE的图标并保存为BMP文件
- Elasticsearch技术解析与实战(一)基础概念及环境搭建
- mysql mysqli 修改_php mysqli 增删改查操作
- redis服务端的maxclient和最大连接空闲时间设置
- a卡 n卡 html5性能,实测说明,A卡N卡测试平台
- PCB制作仿真、自制51板测试及性能改进
- 中国行政区划代码,包括五级行政区划详细代码,县级以上区划地理围栏
- #10098. 「一本通 3.6 例 1」分离的路径
- figma安装包_Figma软件下载|UI界面设计软件(Figma)下载 v3.0.4 官方版 - 比克尔下载...
- segmentation_models.pytorch实战:使用segmentation_models.pytorch图像分割框架实现对人物的抠图
- c语言break可以跳出for循环吗,怎么跳出for循环
- DELL服务器 一般内存模块安装原则
- vm虚拟机安装以及镜像和网路配置
- 人工智能教你识别口红色号
- 分享时的缩略图不显示问题
- 【备忘】【不定时更新】那些有用有趣的网站君们~~
- 无人机寻迹要两个单片机吗_基于OpenMV的循迹无人机设计
- 关于文献HEVC-The New Glod Standard For Video Compress的理解
- 2019年谷歌SEO排名主要因素