var
- 1.在全局作用域中,var声明的变量是全局的,在局部作用域中,使用var声明后是局部,不使用var声明,是全局
- 2.存在变量提升,会导致闭包等问题
- 3.在同一个作用域内,允许重复声明
暂时性死区:
ES6中明确规定,如果块级中存在let和const命令时,则这个区块对这些命令声明的变量从一来是就形成封闭的区域,在代码块内,使用let命令前,该变量都是不可用的,这块区域在语法上称为暂时性死区
意思是说由let/const声明的变量,当它们包含的词法环境(Lexical Environment)被实例化时会被创建,但只有在变量的词法绑定(LexicalBinding)已经被求值运算后,才能够被访问。
当程序的控制流程在新的作用域(module, function或block作用域)进行实例化时,在此作用域中的用let/const
声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,也就是对声明语句进行求值运算,所以是不能被访问的,访问就会抛出错误。
所以在这运行流程一进入作用域创建变量,到变量开始可被访问之间的一段时间,就称之为TDZ(暂时死区)。
let
1.let声明的变量不会挂载到全局对象
2.使用let声明的变量,不允许在当前作用域范围内重复声明
3.将js中的程序变成了一个块级作用域
let a = 1;
function foo() {
console.log(a); //会报错
let a = 2;
}
foo();
以上代码会报错,因为
let原理
从let位置开始,到当前代码块底部,自动建立了匿名函数自调
let在底层还悄悄修改了内部 的变量名,比如let t
-> let _t
const
ES6中专门声明常量的关键字
const声明的变量,必须在声明的时候就赋值,一经赋值不能改变,赋相同的值也不可以
与let的区别:
const一旦声明就必须赋值
const声明如果是一个原始类型的常量,一旦声明就无法修改;
const声明如果是一个引用类型的常量,一旦声明,保存在const中的地址值无法修改,但是通过地址值指向的对象的属性还是能够修改的
注意:
在循环中,let声明的循环变量,会特殊处理,每次进入循环体,都会开启一个新的作用域,并且将循环变量绑定到该作用域(每次循环,都是一个全新的循环变量),循环结束后会自动销毁
三者的区别
var let const 对比总结:
3个方向:1值是否能改变,2作用域在哪,3是否存在变量提升
使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象,值能修改。
使用let声明的变量,其作用域为该语句的代码块内,不存在变量提升,值能修改。
使用const声明的常量,其作用域为该语句的代码块内,不存在变量提升,且常量的值不能修改(原始类型的值和内存地址值不能修改)。
在let/const声明之前就访问对应的变量与常量,会抛出ReferenceError错误;但在var声明之前就访问对应的变量,则会得到undefined