前端开发那些事让前端飞

关于JavaScript变量提升那点事儿

2017-08-14  本文已影响0人  MonkeyDwwl

ECMAScript在浏览器端运行被称为JavaScript

在浏览器端JavaScript是一种描述型脚本语言,不需要编译成中间语言,而是由浏览器按代码块顺序进行动态地解析与执行。

关于作用域

ES6之前,只有全局作用域和函数作用域;ES6引入了块级作用域。作用域是代码执行过程中的变量、函数或者对象的可访问区域。

关于变量的生命周期

变量的生命周期包含着变量声明、变量初始化、以及变量赋值三个步骤;其中声明步骤会在作用域中注册变量,初始化步骤负责为变量分配内存并且创建作用域绑定,此时变量会被初始化为 undefined,最后的分配步骤则会将开发者指定的值分配给该变量。

关于预编译

JavaScript代码不需要编译成一个其它可执行的文件,但是js代码在执行之前会有一个准备过程,这个准备过程叫作预编译。
预编译的过程是不可见的,也不会产生额外的文件。

预编译期间会主要完成两件事情:

  1. 按顺序扫码代码块,如果发现语法错误,停止工作并报错;
  2. 若没有语法错误,做声明变量和初始化变量的操作即所谓的变量提升操作;

先看一道简单的题目

<script type="text/javascript">
    console.log(a);
    var a = 666;
    console.log(a);
</script>  

这道题目很简单,但是却很能说明问题。

提升操作

具体细节如下

只提升加var的变量,没有var不提升


如图,没有var,变量名没有提升,相当于没有声明变量a就直接使用它,会出现引用类型错误。

if结构中的变量提升


如图所示,变量提升一定是发生在预编译期(提升之后才会进入代码的执行期),而变量的提升与if条件语句是否成立无关。只要有var就会提升。

for循环中的变量提升


同样会做变量提升。

函数内部的变量提升


函数内部定义的变量,不可能提上到函数的外部。如图会直接报错。

函数内部的变量只会体升到函数的开始位置。

只提升声明式定义的函数

定义函数有两种方式:


函数提升是整个函数体提升,变量提升是提升的变量名。

如上图所示,通过表达式定义的函数提升,报了一个TypeError的错误;是因为预编译期将var关键字提升,也就是说这里的f就是一个普通变量,它的初值被赋为undefined;当代码执行到第11行f();时就相当于是undefined();,所以肯定会报类型错误。

函数与变量同时提升


当函数名与变量名同名,且同时提升,以函数为准。
理由是函数是一等公民,地位高于变量。

提升不能跨script标签

开始那道题的答案

ES6中的变量提升以及暂时性死区

在 ES6 中以 let 与 const 关键字声明的变量会在作用域头部被初始化,不过这些变量仅允许在实际声明之后使用。在作用域头部与变量实际声明处之间的区域就称为所谓的暂时死区(Temporal Dead Zone),TDZ 能够避免传统的提升引发的潜在问题。

小结

以上,就是关于JavaScript变量提升的知识小结。

上一篇下一篇

猜你喜欢

热点阅读