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
对象
不太理解