{ let a = 10; } console.log(a) //ReferenceError:a is not defined
let不像var那样会发生“变量提高”现象,因此,变量必定要在声明后使用,否则就会报错。javascript
console.log(a) //ReferenceError:a is not defined let a = 10;
只要块级做用域内存在let关键字,它所声明的变量就绑定这个区域,再也不受外部影响。java
var tmp = 20; if(true){ tmp = 'abc'; //ReferenceError:tmp is not defined let tmp; }
上面的代码中存在全局变量tmp,可是块级做用域内let又声明了一个局部变量tmp,致使后者绑定了这个块级做用域,因此在let声明变量前,对tmp赋值会报错。函数
ES6明确规定,若是区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就造成封闭做用域。只要在声明以前使用这些变量,就会报错。在语法上称为“暂时性死区(temporal dead zone,TDZ)”
code
有时候,会不经间遇到比较隐蔽的“死区”,不太容易被发现。对象
function bar(x=y,y=2){ return [x,y]; } bar() //报错
上面的代码中是由于参数x的默认值等于另外一个参数y,而此时y尚未声明,属于死区。ip
let不容许在相同的做用域内
声明同一个变量。内存
function bar(){ let a = 10; var a = 20; } //报错 function bat(){ let a = 10; let a = 20; } //报错
所以,因此也不能在函数内重复声明参数:作用域
function bar(args){ let args = 10; } bar() //报错 function bar(args){ { let args = 20; } } bar() //不报错
外层代码块不受内层代码块的影响。io
外层做用域没法读取内层做用域的变量。console
内层做用域能够定义外层做用域的同名变量。
块级做用域的实现,使得普遍使用的自执行匿名函数(IIFE)变得再也不必要了。
//自执行模式 (function(){ var a = 10; })() //块级做用域写法 function(){ let a = 10; }
函数自己的做用域也在其所在的块级做用域以内。
const用来声明常量。一旦声明,其值就不能再改变。
const PI = 3.1415; const PI = 3 //TypeErrorL "PI" is read-only
const声明的变量不得改变值,意味着const一旦声明常量就必须当即初始化,不能留到后面赋值。
const与let关键字同样,只在声明所在的块级做用域内有效;const关键字声明的常量也不提高,一样存在暂时性死区,只能在声明后使用。
对于复合型数据类型,常量名不指向数据,而是指向数据所在的地址。const关键字只是保证常量名指向的地址不变,并不保证该地址的数据不变,因此将一个对象声明为常量必须注意该点。