块级作用域
作用域原本包含全局作用域和函数作用域。现在ES6带来了块级作用域。
变量提升
平时我们都是通过 var 来声明变量,每当我们使用 var 时都会涉及到变量提升。什么是变量提升呢?我们先来看一段代码。
console.log(a) //undefined
var a = 'JavaScript'
console.log(b) //b is not defined
我们可以看到此时打印 a 是不会报错的。其实一个变量是分为声明和赋值两部分的,引擎在正式执行代码之前会进行一次预编译,此时变量会被提前存到内存中。所以第一个 a 会打印 undefined。基础的变量提升就是这样。
let和const
因为变量提升的存在,代码的执行会出现不按顺序的情况。块级作用域能较好的解决这个问题,其实块级作用域的作用就是代码写在哪,就在哪里执行,定义在代码块中的变量在代码块执行结束后会被销毁掉。ES6中的 let 和 const 就是拿来实现块级作用域的。
let 和 const 的用法var的使用方法类似。不过他们声明的变量不存在变量提升,且只能起作用在特定代码块。
console.log(a) //a is not defined
let a = 'JavaScript'
console.log(a) //a is not defined
const a = 'JavaScript'
function foo()
{
if(true){
let a = 'aaa'
console.log(a)
}
console.log(a)
}
function bar()
{
if(true){
var b = 'bbb'
console.log(b)
}
console.log(b)
}
bar() // bbb bbb
foo() // aaa a is not defined
function foz()
{
if(true){
const c = 'ccc'
console.log(c)
}
console.log(c)
}
foz() //ccc c is not defined
注意虽然 let 和 const 很像,但他们还是有区别的。const 声明的是常量,常量是不能被更改的。但是 const 声明的对象的内部的值是可以被修改的,不过指针所指向的地址是不能被改变的。
const a = 'aaa';
a = 'bbb'; // TypeError: Assignment to constant variable.
let a = 'aaa'
a = 'bbb'
console.log(a) //bbb
const person = {
name:'张三',
age:20
}
person.name = '李四'
console.log(person) //{ name: '李四', age: 20 }
同样需要注意的是,let 和 const 不能重复声明。下面是几个基础例子。
let a = 'aaa'
let a = 'bbb' //'a' has already been declared
let a = 'aaa'
const a = 'bbb' //'a' has already been declared
let a = 'aaa'
var a = 'bbb' //'a' has already been declared
思考
我们可以知道在ES6面世之前是没有块级作用域这一说法的,那么块级作用域是如何实现的呢?变量提升又是如何实现的呢?