ES6 的一个重要特性就是有了块的概念,引入了let、const声明变量,在刚开始接触这两个标识符的时候,就当作var来用的,可是他们之间实际上是有不少差异的。本篇整理了一下,简单的地方只是列了一个提纲,文末还有他们之间的区别,当用到的时候能够回来看。node
js中对于未声明的变量会报语法错误,对于未初始化值的变量会报undefined。编程
做用域:函数做用域、全局做用域浏览器
变量提高:变量的==声明位置==提高到当前做用域顶部,可是变量的==初始化位置==不变。安全
块级声明 ----->块级标识符----->let、constbash
----->块级做用域(亦称词法做用域):指函数内部、{}之间的区域函数
块级变量只在代码块内有效,代码块外当即销毁。ui
要求声明时必须进行初始化,且值一旦被设定后不可更改。spa
可是对于js对象而言, const声明不容许修改绑定,可是容许修改绑定的值设计
ES6 明确规定,若是区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就造成了封闭做用域。凡是在声明以前就使用这些变量,就会报错。code
总之,在代码块内,使用let命令声明变量以前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
临时死区内,使用该变量,如:typeof,都会报语法错误; 若是没有造成临时死区,使用该变量,typeof,则不会报错。 例:2.4.二、2.4.3
2.4.1
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
复制代码
2.4.2
typeof x; // ReferenceError
let x;
复制代码
上面代码中,变量x使用let命令声明,因此在声明以前,都属于x的“死区”,只要用到该变量就会报错。所以,typeof运行时就会抛出一个ReferenceError。
做为比较,若是一个变量根本没有被声明,使用typeof反而不会报错。
2.4.3
typeof undeclared_variable // "undefined"
复制代码
上面代码中,undeclared_variable是一个不存在的变量名,结果返回“undefined”。因此,在没有let以前,typeof运算符是百分之百安全的,永远不会报错。如今这一点不成立了。这样的设计是为了让你们养成良好的编程习惯,变量必定要在声明以后使用,不然就报错。
有些“死区”比较隐蔽,不太容易发现。
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错
复制代码
上面代码中,调用bar函数之因此报错(某些实现可能不报错),是由于参数x默认值等于另外一个参数y,而此时y尚未声明,属于“死区”。若是y的默认值是x,就不会报错,由于此时x已经声明了。
function bar(x = 2, y = x) {
return [x, y];
}
bar(); // [2, 2]
复制代码
另外,下面的代码也会报错,与var的行为不一样。
// 不报错
var x = x;
复制代码
// 报错
let x = x;
// ReferenceError: x is not defined
复制代码
上面代码报错,也是由于暂时性死区。使用let声明变量时,只要变量在尚未声明完成前使用,就会报错。上面这行就属于这个状况,在变量x的声明语句尚未执行完成前,就去取x的值,致使报错”x 未定义“。
var:for与 for in、 for of let:for与 for in、 for of const:for与 for in、 for of
默认使用const,只在确实须要改变变量的值时才使用let。
一、变量提高:var声明的变量会变量提高,而块级标识符不会。
二、变量重命名:var容许同一个做用域下变量重名,可是会覆盖,而块级标识符不容许在同一个做用域下变量重名。
三、全局做用域绑定: var声明的变量,若是和全局对象相同,则仍然是覆盖原则。 而块级标识符和全局对象没有任何关系。
全局对象:浏览器环境中是window,node环境中是global。
var a = 2;
var a = 3; // a=3
复制代码