深入了解var
...大约 3 分钟
在ES6出现之前,我们都是使用var这个关键字来声明一个变量的,但是其弊端非常多。因此,在学习let和const之前,必须先了解一下var。var有以下两个特点。
- 无块级作用域
- 存在变量提升(Hoisting)
1.无块级作用域
在ES5中,作用域一般划分为全局作用域和局部作用域。其中,局部作用域也叫“函数作用域”。ES6新增了块级作用域的概念,块级作用域就是通过let或const来体现的。那么块级作用域究竟是怎样的呢?举个简单的例子,我们都知道条件语句、循环语句等是使用大括号“又”来进行代码块处理的。如果存在块级作用域,那么“B”内部定义的变量,在“0”外部是没办法访问到的;如果不存在块级作用域,那么“0”内部定义的变量,在“0”外部是可以访问得到的。对于块级作用域,用最简单的一句话来说就是,如果一门语言存在块级作用域,那么一对大括号定义的就是一个块级作用域。
举例:ES5中的var
if (true) {
var name = 'ss'
}
console.log(name)
>>> ss
分析
ES5是不存在块级作用域的(这里不考虑try...catch)
在条件语句大括号中使用var声明的变量,我们在大括号外面也访问得到。
2.存在变量提升
在ES5中使用var来声明变量,会出现一个奇怪的现象:变量提升。那么变量提升是什么呢?我们先来看一个例子
举例:var声明的变量
console.log(a);
var a = 2023;
>>> undefined
分析
所谓的变量提升,指的是如果你使用var来声明一个变量,那么JavaScript从上到下执行代码的时候,会做一定的预处理,其工作原理如下所示
当进入一个Javascript环境时,JavaScript引擎并不是立刻直接从上到下执行代码的,而是先扫描所有代码,将var声明的变量集合在一起,组成一个词法环境(Lexical Environment,LE)
所以对于这个例子来说,如果JavaScript立刻从上到下执行代码,那么console.log(a);这一句代码就会报错,因为运行到这里时,JavaScript并不知道a是什么。但是实际情况是JavaScript先扫描整个代码,然后把vara;提升到顶部,即先声明a,此时a的值就是underined
// 也就是说,上面的例子等价于以下代码。
var a
console.log(a)
a = 2023
变量提升是ES5的内容,它本身比较复杂。本书讲的是ES6,所以这里只是简单介绍了一下。ES5基础薄弱的小伙伴,一定要去搜索、了解一下,因为这个概念可以说是前端岗位面试中必考的知识点之一。
