前言
个人一直认为 let
和 var
完全一样,所以接触了ES6后就一直用let
声明变量
直到有一次在看 “this指向” 相关的内容的时候,发现了一个问题
let a = 1;
function test() {
console.log(this.a);
}
test();// 结果: undefined ???
上面的test(),相当于window.test(),也就是说 let
声明的变量并没有在window对象下
但是用var
代替let
来声明变量的话,是能获取到值的
let a = 1;
var b = 1;
console.log(window)
看了下window对象的内容,确实如此
到这我有三个疑问
- 为什么
let
声明的变量不在window下 - 既然不在window下,那它在哪呢
- 为什么平时使用的时候,完全没有影响呢
为什么不在window下
注:其实不止let,const 和 class 声明的变量也不在window下
首先看几个概念
- 声明变量的方式:
- ES5:var & function
- ES6:let & const & class
- 顶层对象:
- 浏览器中的顶层对象就是
window
对象,在Node中就是global
对象
- 浏览器中的顶层对象就是
为什么不在window下
在ES5中顶层对象的属性与全局变量挂钩,即,自己声明的全局变量,会成为顶层对象(window)的一个属性
这导致了几个问题
没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的)
程序员很容易不知不觉地就创建了全局变量(比如打字出错)
最后,顶层对象的属性是到处可以读写的,这非常不利于模块化编程
window
对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。 摘自阮一峰老师的ES6入门——链接
ES6为了规避这些问题,而且要保持ES5的兼容性,所以var & function声明的变量依然在顶层对象中,而ES6的let & const & class不属于顶层对象的属性
let声明的对象到底在哪
let a = 1;
function test() {};
console.dir(test);
注:console.dir
显示指定对象的所有属性
在查找全局变量时,会去[[Scopes]]
中取值,所以平时使用时这几种声明方式都不会影响我们取值