let/const作用域提升
1)根据前面所学的内容知道,var定义的变量是可以作用域提升的。
console.log(foo); // undefined
var foo = "foo"
虽然在第一行中foo还没有被定义,但是在执行代码前,会预编译,先定义foo,但是还没有被赋值,因此是undefined。(参考闭包那节中内容)
2)如果使用let(const是同样道理)声明的变量,在声明之前访问就会报错。
// 报错:ReferenceError(引用错误): Cannot access 'foo' before initialization(初始化)
console.log(foo);
let foo ="foo"
所报的错误是:
3)那么是不是foo变量只有在代码执行阶段才会被创建呢?不是,可以看一下ECMA262对let和const的描述:这些变量会被创建在包含他们的词法环境被实例化时,但是是不可以访问他们的,直到词法绑定被求值。
可以理解为当这个执行上下文被创建出来的时候,foo变量就已经被创建了,不需要执行到上述第三行代码,就已经被创建了,但是直到这个变量被赋值之前都不能访问它。
根据这个意思,也就是说执行到上述第二行代码的时候,foo已经被创建了,但是不能够被访问,一直到它被赋值才能访问。
4)那么let和const有没有作用域提升呢?
从上面可以看出,在执行上下文的词法环境创建出来的时候,变量事实上已经被创建了,只是这个变量是不能被访问的,那么变量已经有了,但是不能被访问,是不是一种作用域提升呢?
事实上维基百科并没有对作用域提升有严格的概念解释,那么从字面量上理解:
- 作用域提升:在声明变量的作用域中,如果这个变量可以在声明之前被访问,那么我们称之为作用域提升。
- 在这里虽然被创建出来了,但是不能被访问,不能被称之为作用域提升。
因此这里的观点是:let和const没有进行作用域提升,但是会在执行上下文创建阶段被创建出来。