let和const命令
1、let命令
2、块级作用域
3、const命令
4、顶层对象的属性
5、global对象
1、let命令
ES6在ES5的基础上新增了let命令,用来声明变量,用法类似var,但是let所声明的变量,只在let命令所在的代码块内有效。
for循环的计数器,就很适合使用let命令
----计数器i只在for循环体内有效,在循环体外引用就会报错。
----变量i是var声明的,在全局范围内都有效,所以每次循环,新的值就会覆盖旧的值。
在这里要注意的是:使用let声明的变量仅在块级作用域内有效。ES5中没有块级作用域。
在其他C的语言中,由花括号封闭的代码都有自己的作用域(如果用ECMAScript的话来讲,就是它们自己的执行环境)如果是在C,C++或Java中,变量会在if语句执行完毕后销毁,但是在没有块级作用域的情况下,if语句中的变量声明会将变量添加到当前的执行环境(在这里是全局环境)。
对于有块级作用域的语句来说,for语句初始化表达式所定义的变量,只会存在于循环的环境之中。
不存在变量提升
var会发生变量提升。即变量可以在声明之前使用。let和var的使用情况刚好相反。
暂时性死区
本质:只要进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那行代码出现,才可以获取和使用该变量。
2、块级作用域
之所以在ES6中新增块级作用域,是因为ES5只有全局作用域和函数作用域,带来很多不合理的场景:
1)内层变量可能会覆盖外层变量,原因在于变量提升导致的。
2)用来计数的循环变量泄露为全局变量。对于JavaScript来说,由for语句创建的变量即使在for循环执行结束后,也依旧会存在于循环外部的执行环境中。
ES6的块级作用域
let实际上为了JavaScript新增了块级作用域。
ES6允许块级作用域的任意嵌套。
{{{ let example = "hello"}
console.log( example );
}}报错,原因:外层作用域无法读取内层作用域的变量
内层作用域可以定义外层作用域的同名变量
{{{
let example = "hello";
{ let example = "hello" }
}}}
块级作用域与函数声明
ES5规定,函数声明只能在顶层作用域和函数作用域中声明,不能在块级作用域声明。
ES6引入了块级作用域,在块级作用域中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
为了减轻用let产生的不兼容问题,ES6的浏览器可以不遵守上面的规定,有自己的规则:
----允许在块级作用域内声明函数。
----函数声明类似var,即会提升到全局作用域或函数作用域的头部。
----同时,函数声明还会提升到所在的模块作用域的头部。
根据以上三条规则,在浏览器的ES6环境中,块级作用域声明的函数行为类似于var声明的变量,但是若在块级作用域内只声明函数,没定义函数(一种情况),会报错。
如果确实需要在块级作用域内声明函数,也应该写成函数表达式,而不是函数声明结构。
还有要注意的是:ES6的块级作用域允许声明函数的,只在使用大括号的情况下使用。如果没有大括号,报错。
Do表达式
块级作用域将两个语句封装在一起,let声明变量,域外得不到变量的值,除非该变量是全局变量。
但有一个方法,在块级作用域前加上do,变为do表达式,可以返回值。
3、const命令
const声明一个只读的变量,一旦声明,常量的值就不能改变。
const的作用域与let命令相同:只能在声明所在的块级作用域内有效。
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
const声明的变量,也与let一样,不可重复使用。
对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变。
若想冻结对象,应该使用odject.freeze方法。