前言

刚接触到JavaScript的时候,便知道JavaScript是按顺序执行的,是如浏览器的解析DOM树一样的流程,解析DOM结构的时候,如果遇到JS脚本或者外联脚本便会停止解析,继续下载脚本之后,执行脚本,然后再解析DOM。

然而,却因此常常碰到问题。

看如下代码以及输出:

var name;
console.log(name); // undefined
name = 'tom'; age = 10;
var age;
console.log(age); // 10

  

上面的代码让我们产生了疑惑,我们仅仅声明了name的时候,打印出来值是undefined,按理说,重新声明age之后,age的值应该也是undefined才对,但是输出来的却是10。这究竟是怎么回事儿呢?

我们的通用解释是,遇到了变量提升。

而这样的情况,我们在函数中也会看到,请看下面代码:

log();
console.log(name);
var name = 'tom';
function log() {
console.log('this is log');
}

  

上面代码的输出结果是什么?

输出结果:
this is log
undefined

  

为什么会产生这样的情形呢?我们通用的解释是,函数声明提升了。

而针对这两种情况,就是我们经常遇到的提升机制,也就是我们常说的Hoisting。

而仅仅只是一句提升机制来解释这种现象,还是觉得云里雾里,要是我之前可能也就不明觉厉的哦了一声,然后就不再理会这样的东西了,那么究竟为什么会出现这样的情况呢?

JavaScript是如何被编译的呢

有时候我们会想,一段JS代码是如何执行的呢?其实,在JS代码被执行之前,通常都有一个编译过程。

这个编译过程其实很复杂,但总体来说,逃不过编译过程的步骤,只不过JavaScript是在这个步骤之中对代码做了优化处理。

第一、词法分析

词法分析主要是将一段程序分解成有意义的代码块,便于对分解的代码块做解析。

比如,var age = 10;这一段代码将会被分解成 var、age、=、10、;。这是5个词法单元。

这些单元分析完毕之后,便会给解析器调用,生成相应的AST(抽象语法树)。

第二、解析词法单元

解析词法单元,是为了生成AST,那么到底什么是AST呢,我们来看一段代码以及解析生成的AST。

同样是var age = 10;这段代码,被解析器解析成了一段树形结构的结构,这个结构,就是抽象语法树AST。你可以通过这个网站来查看生产的AST:AST解析器

而抽象语法树,又是可以转换成可执行代码。这就涉及到编译的第三个阶段。

第三、生成可执行代码

生成可执行代码的过程,相当于是再把AST转换成浏览器可执行的代码,或者是各种语言引擎可执行的代码。

比如我们常见的babel,可以让我们用ES6的语法去开发程序,其实就是依靠babel编译器,将我们的ES6代码编译成ES6的AST,然后将ES6的AST转换成ES5的AST或者ES3的AST,最后将AST转成ES5或ES3的代码来让浏览器执行。

同理,TypeScript的TSC也是一个编译器,做的事情和babel是一样的,只不过两者编译出来的ES6的AST有略微的差别,这样就造成了TypeScript用不了Babel社区的丰富多样的插件,如eslint等。

因为eslint语法检查,正是基于AST做的。

那么上面这个编译过程有什么用呢?

JavaScript中的声明和赋值

理解了语言的编译过程,那么JavaScript中的声明和赋值又是如何的一个流程呢?

比如,var age = 10;这段代码,在JavaScript中的编译方式是如何呢?

在JavaScript中,这段代码大概相当于是如下两个过程:

var age = undefined;     // 隐式赋值,编译阶段
age = 10; //变量赋值 执行阶段

  

函数声明也是如此:

// 这一段代码就是一个完整的函数声明,在编译阶段中,会先执行所有声明,才会依次执行代码操作。
function log() {
console.log('this is log')
}

  

这个时候,我们再回头来,想一下提升机制是什么?

再看提升

JavaScript的执行,被分为了两个阶段,分别是编译阶段,以及执行阶段。依照这个来看,所谓的提升机制(有的叫做变量提升,考虑到函数的定义,并未用这个名词),就是JavaScript引擎把变量声明和函数声明在编译阶段首先进行默认赋值,之后,在程序执行阶段,才会被代码真正的执行。也就是说,针对声明先提升,后执行。

注意:函数声明和变量都有提升机制,两者之间也有优先级。这都遵循一个原则:函数优先原则。也就是说,函数声明会提升到普通变量声明之前。

总结

变量提升,是一个值得去探究的概念,只有理解了这个概念,我们理解JavaScript的执行机制将会变得清晰明了起来。

文中有什么描述不当的,希望各位大佬能指出,大家共同学习,一起进步。

我的博客:http://www.gaoyunjiao.fun/?p=143

漫谈JavaScript中的提升机制(Hoisting)的更多相关文章

  1. JavaScript中变量提升------Hoisting

    原谅链接:http://www.cnblogs.com/damonlan/archive/2012/07/01/2553425.html 因为这个问题很是经典,而且容易出错,所以在介绍一次.哈哈.莫怪 ...

  2. javascript中变量提升的理解

    网上找了两个经典的例子 var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); // 10 var ...

  3. JavaScript中变量提升是语言设计缺陷

    首先纠正下,文章标题里的 “变量提升” 名词是随大流叫法,“变量提升” 改为 “标识符提升” 更准确.因为变量一般指使用 var 声明的标识符,JS 里使用 function 声明的标识符也存在提升( ...

  4. 漫谈JavaScript中的作用域(scope)

    什么是作用域 程序的执行,离不开作用域,也必须在作用域中才能将代码正确的执行. 所以作用域到底是什么,通俗的说,可以这样理解:作用域就是定义变量的位置,是变量和函数的可访问范围,控制着变量和函数的可见 ...

  5. javascript 中的事件机制

    1.javascript中的事件. 事件流 javascript中的事件是以一种流的形式存在的. 一个事件会也有多个元素同时响应. 有时候这不是我们想要的效果, 我们只是需要某个特定的元素相应我们的绑 ...

  6. Android与javascript中事件分发机制的简单比较

    在前面两篇博客中,我们讨论了Android中的事件分发的相关内容,那么在本篇博客当中,我们就简单探讨一下html或javascript中的事件分发机制,并进行简单的对比. 在前端中,对事件进行绑定有三 ...

  7. Javascript中的反射机制(五)

    一: 什么是反射机制 反射机制指的是程序在运行时能够获取自身的信息.例如一个对象能够在运行时知道自己有哪些方法和属性. 二: 在JavaScript中利用for(…in…)语句实现反射 在JavaSc ...

  8. JavaScript中的垃圾收集机制

     JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存. 在编写 JavaScript 程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的 ...

  9. JavaScript的变量提升机制

    变量提升 JavaScript的变量提升有两种,用var声明的变量以及用function声明的变量. 用var声明的变量 我们先来看下面这段代码,a的值是多少 代码1 console.log(a); ...

随机推荐

  1. 【转载】C# 中的委托和事件(详解)

    <div class="postbody"> <div id="cnblogs_post_body" class="blogpost ...

  2. LeetCode :2.两数相加 解题报告及算法优化思路

    题目连接:2.两数相加 题意 题目难度标为 中等, 因为题意上有一部分理解难度,以及需要数据结构的链表基础. 还不知道到链表的童鞋可以粗略的看下百度百科或者是翻出数据结构的书看一看,通俗一点的语言来解 ...

  3. Compatibility模式安装windows7后改为AHCI模式无法启动Windows7的解决办法

    在用Compatibility模式安装Windows 7后,再在BIOS中去开启SATA硬盘的AHCI功能的话,就会出现无法启动的情况.只有改回Compatibility模式后,系统才恢复正常.经过试 ...

  4. mybatis一对多双向映射

    连表查询 select   id  resultType  resultMap resultType和resultMap不能同时使用 association 属性  映射到多对一中的“一”方的“复杂类 ...

  5. 使用bibtex为latex论文添加参考文献

    此文以引用Shannon的Prediction  and  Entropy  of Printed  English为例 1. bib文件 1.1 准备工作 进入Google Scholar 点击设置 ...

  6. JavaWeb零基础入门-01 基础概念说明

    一.序言 从学校出来到实习,发现学校学的东西太过基础,难于直接运用于工作中.而且工作中,现在都以web开发为主,学校开了web开发相关课程.自己学的不够深入,所以本人自学JavaWeb开发,介于学习巩 ...

  7. 微信小程序页面跳转url如何传对象参数

    两步走 首先第一步:wx.navigateTo({ url:"XXX"+"&params="+ JSON.stringify(obj); }) 第二步获 ...

  8. monkey学习总结笔记

    一.什么是monkey? Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用程序 ...

  9. net core 3.0 之Grpc新特性小试牛刀

      相信微服务大家伙都有听说和知道,好处弊端咱也不多说了,Grpc算是一个比较全面的微服务框架,也得到微软的支持 总结下来就是,跨平台,可靠,通信快,扩展性强,网络消耗小,模板多语言通用 光说好处,没 ...

  10. 自己搭建传统ocr识别项目学习

    大批生成文集训练集: https://www.cnblogs.com/skyfsm/p/8436820.html 基于深度学习的文字识别(3755个汉字) http://www.cnblogs.com ...