漫谈JavaScript中的提高机制(Hoisting)

前言

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

然而,却所以经常碰到问题。java

看以下代码以及输出:浏览器

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

age  = 10;
var age;
console.log(age);  // 10

  

上面的代码让咱们产生了疑惑,咱们仅仅声明了name的时候,打印出来值是undefined,按理说,从新声明age以后,age的值应该也是undefined才对,可是输出来的倒是10。这到底是怎么回事儿呢?babel

咱们的通用解释是,遇到了变量提高。函数

而这样的状况,咱们在函数中也会看到,请看下面代码:学习

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

  

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

输出结果:
this is log
undefined

  

为何会产生这样的情形呢?咱们通用的解释是,函数声明提高了。网站

而针对这两种状况,就是咱们常常遇到的提高机制,也就是咱们常说的Hoisting。this

而仅仅只是一句提高机制来解释这种现象,仍是以为云里雾里,要是我以前可能也就不明觉厉的哦了一声,而后就再也不理会这样的东西了,那么究竟为何会出现这样的状况呢?.net

JavaScript是如何被编译的呢

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

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

第1、词法分析

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

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

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

第2、解析词法单元

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

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

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

第3、生成可执行代码

生成可执行代码的过程,至关因而再把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

相关文章
相关标签/搜索