ES5中声明变量的关键字仅有var
,无块级作用域概念,ES6中新增变量声明关键字let
和const
可以实现声明局部变量和静态变量,因此出现了块级作用域概念。
ES5中变量声明问题
ES5中作用域可分为全局作用域和函数作用域。在全局执行环境中声明的变量即为全局变量,在全局环境中有效。在函数体内部通过var
声明的变量为局部变量,仅在函数体内部有效。函数体外部不能直接(通过闭包方式可以访问函数体内部变量)访问。这一点和诸如C、Java之类静态编程语言类似。另外子执行环境中可以直接访问父执行环境中变量,反之则不行。
var变量提升
var关键字声明变量存在变量提升问题。即在变量作用域内声明变量时,变量声明操作会被提升到最顶部,变量调用不受声明语句在其作用域内出现的先后顺序影响。
1 | function func(){ |
执行上述代码,最终输出haha
和undefined
。这一点和C这类静态语言大不相同,如果在C中,这段代码会报错,因为函数内最后输出a
在condition
为true
时才会被创建。但是在JavaScript
中利用var
声明变量,会造成造成变量提升。上述代码相当于在函数体最顶端声明通过var a
声明了变量a
,当condition
值为true
时给变量a
赋值。所以最后一句输出没有报错,由于a
仅声明,未赋值,所以最后会输出ubdefined
。
var声明变量覆盖宿主全局变量
JavaScript
需要在诸如node.js
、浏览器这类宿主环境中执行。这些宿主环境自带一些全局变量,利用var声明名称和宿主环境中的全局变量名一样的变量,则新声明的变量会覆盖原有全局变量。如在浏览器中的全局变量都存放在对象window
中,例如正常情况下通过window.innerHeight
可以返回浏览器可视窗口的高度。但是如果在浏览器环境中,声明var innerHeight = "Hello"
,则会覆盖window.innerHeight
的值,最终会返回Hello
。
ES6中变量声明问题
ES6中增加了变量声明关键字let
和const
,这两个关键字可以声明,仅在块级作用域内部访问的变量。这两个关键字不能重复声明变量,即如果变量在之前已经声明过,再用这两个关键字重复声明会报错。同时这两个关键字声明变量不存在变量提升,即在变量声明之前,调用变量会报错。其中const
声明静态变量,需要在声明的同时赋值。如下代码展示了let
和const
的相关要点:
1 | var a = true; |
let
和const
的特性使得JavaScript
的作用域增加了块级作用域。