let:
-
所声明的变量,只在let 命令所在的代码块内有效
-
如果在代码块外调用 let 声明的变量会报错 (xx is not defined)
-
for 循环的计数器 很适合 let 命令
-
不存在变量提升 4.1 使用 var 命令会发生 变量提升的现象, 即变量可以在声明之前使用,即 undefined 4.2 let 改变了这种语法行为, 他所声明的变量一定要在声明之后使用。
-
暂时性死区:(TDZ) 5.1 只要块级作用域内存在let 命令, 它所声明的变量就绑定(binding) 这个区域,不再受外部的影响 5.2 ES6有明确规定,如果区块内使用let和 const 命令, 这个区块对这些命令声明的变量,从一开始是的时候就形成了封闭的作用域。凡事在声明之 前就使用这些变量就会报错
-
不允许 重复声明 let 不允许在相同的作用域内重复声明同一个变量 ,不能在函数内部重新声明参数
let --> Es6的块级作用域
- 外层代码块不受内层代码块的影响
- ES6允许 块级作用域 的任意嵌套 {{{{{let insane = 'Hello World'}}}}};
- 外层作用域无法读取内层作用域的变量
- 内层作用域可以定义 外层作用域的同名变量
- 块级作用域的出现, 实际上使得 广泛使用的立即执行函数表达式不再必要了
const
- const 声明一个只读的常量, 一旦声明, 常量的值就不能改变(为之后const 的本质解释做出铺垫)
- const 声明的变量不得改变值,这意味着, const 一旦声明变量, 就必须立即初始化。不能留到以后赋值。
- const 的作用域 与 let 命令相同,只在声明所在的块级作用域内有效
- const 命令声明的常也是不提升的, 同样存在暂时性死区,只能在 声明位置后面使用
- const 声明的常量, 也与 let 一样不可重复声明
const的本质:
-
const 实际上保证的,并不是变量的值不得改动, 而是变量指向的那个内存地址所保存的数据不得改动
-
对于简单的数据类型来说,值就保存在变量指向的内存地址,因此等于常量。
-
但是对于复合型的数据(数组和对象),变量指向的内存地址,保存的只是一个指向实际数据的指针
-
const 只能保证这个指针是固定的(即总是指向另一个固定的地址),至于他指向的数据结构是不是可变的,就不能控制了。
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
上面的代码中, 常量foo 储存的是一个地址, 这个地址指向一个对象。
不可变的只是这个地址,即不能把 foo 指向另一个地址, 但对象本身是可变的,
所以依然可以为其添加新属性
const a = [];
a.push('Hello'); // 可执行
a.length = 0; // 可执行
a = ['Dave']; // 报错
上面代码中, 常量a 是一个数组, 这个数组本身是可写的,但是如果将另一个数组赋值给 a 就会报错
如果实在想冻结对象, 应该使用 object.freeze 方法
// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;
ES6 变量声明的 6 种方法
ES5 var、 function
ES6 let, const, import, class
顶层对象属性
在浏览器中 顶层对象 : window 对象 在 NODE 中指的是: global 对象 在ES5中, 顶层对象的属性与全局变量是等价的 ES6 做出了改变, var/ function 声明的全局变量依旧是顶层对象的属性 let, const, class 命令声明的全局变量,不属于顶层对象的属性
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined