let 和 const 命令
let命令
-
声明变量,变量只在
let所在的代码块内有效 -
不会像var一样,提升变量声明,适合应用于
for循环 -
暂时性死区:如果块级区域内有
let变量声明,在其声明语句之前的块级区域部分,为暂时性死区var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
注意:ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
4. 同一作用域内不允许重复声明变量
- 块级作用域
-
避免内层变量覆盖外层变量,外层代码不受内层变量影响,外层变量无法读取内层变量
-
用来的计数的循环变量不会泄露为全局变量
-
作用可以多层嵌套
{},内层变量与外层变量可以相同 -
ES6块级作用域内允许函数声明,外层无法引用;虽然允许,但运行会报错,需要采用函数表达式,不用声明语句
// 函数声明语句 { let a = 'secret'; function f() { return a; } } // 函数表达式 { let a = 'secret'; let f = function () { return a; }; } -
do表达式:块级作用域没用返回值,但可以使用do语句,接收整个块级作用域的返回值let x = do { let t = f(); t * t + 1; };
const命令
-
声明常量,一旦声明,值就不可改变,因此声明后必须立即初始化,不能留到以后赋值
-
与
let作用域类似,只在声明的块级作用域内有效;存在暂时性死区,只能在声明语句后使用 -
const声明的对象类型,对象不可改变,但对象的属性可以操作const a = []; a.push('Hello'); // 可执行 a.length = 0; // 可执行 a = ['Dave']; // 报错
本质:const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。
4. 可以使用Object.freeze将对象进行冻结,下方表达式将对对象及其属性都进行冻结
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
NOTE:ES6声明变量的六种方式:var function let const import class
- 顶层对象的属性
-
var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。var a = 1; window.a // 1 let b = 1; window.b // undefined
global对象
不太理解