let
- 不存在变量提升: var存在函数作用域或全局作用域的变量提升,let不存在变量提升则不可以先赋值后声明,符合正常的开发逻辑
- 不允许重复声明: var允许重复声明并覆盖原来的声明,let不允许,可以避免命名重复带来的问题
- 存在块级作用域: es5只存在函数作用域,块级作用域可避免内层变量覆盖外层变量、也可避免循环时计数变量泄漏到全局
- 存在'暂时性死区':暂时性死区是在块级作用域中如果用let声明了一个变量,不管全局中是否存在这个变量,也不管访问是在声明之前还是之后,他访问到的都是该块级作用域中的该变量,在该块级作用域中仍要满足(不存在变量提升和不允许重复声明两个规则)
const
const除上述的四点之外
- const声明一个常量,不允许重复赋值,除了引用类型内部的值,所以const一旦声明必须赋值,不允许先声明后赋值
两个本质
前提:
-引擎负责整个代码的编译以及运行
-编译器则负责词法分析、语法分析、代码生成等工作
-作用域负责维护所有的标识符(变量)。
简单数据类型声明
a -> 在栈内存中开辟一个内存地址(内存地址中保存的是数据)
引用数据类型声明
a -> 在栈内存中开辟一个内存地址(内存地址中保存的是指向的堆内存中的内存地址) -> 指向堆内存中的一个内存地址(数据保存在堆内存中)
- let不允许重复声明
声明时:编辑器在分析词法作用域的时候,遇到let a的时候,编译器会询问作用域是否已经存在变量a,如果存在则抛出异常,如果不存在则通知作用域声明一个变量a,作用域会给变量a开辟一个内存,本质不能改变变量在堆内存中的内存地址的指向
- const不允许重复赋值
赋值时:引擎遇到a=2时,会询问作用域是否有a这个变量,如果没有则通过var声明一个(非严格模式),如果有,是通过const定义的话则抛出异常
本质是不能改变变量指向的栈内存中的内存地址中的数据,对于简单数据类型内存地址中直接存的是数据相当于常量,对于引用类型内存地址中存的是一个指针,这个指针指向堆内存,所以引用类型只要不改变指针就可以,指针指向的堆内存中的数据可以改变
let解决问题
es5中顶层对象属性等价于全局变量,es6不是,let声明的全局变量a在windows.a是拿不到的
引申问题:this想要解决的问题是浏览器、node和web worker三个的顶层对象拿到的方式不统一,但this也不是一定能拿到顶层对象
this取决于函数调用的方式
以上:自我学习用,只是自己的理解,请多多指教