let基本介绍
在ES6中新增了let与const两个命令,用法类似于var但是最大的不同在于var作用于全域而let与const作用于块状区域
中。
var作用全域 :
for(var i=0;i<5;i++){ //...}//即使i是宣告在for当中,却可以在外部(全域)中呼叫到console.log(i); // 5
let作用块状区域 :
for(let i=0;i<5;i++){ //...}//由于let只作用在块状区域中(for)所以在全域的环境中无法呼叫console.log(i); //i is not defined
var a = [];for(var i=0;i<5;i++){ a[i] = () => { console.log(i); }}a[3](); //5
由于i是透过var所建立的变数,代表着它在全域中都有效所以全域变数中只有一个变量i,
也就是说数组a中的所有成员的i都会指向同一个全域的i也就是最后一轮的i值 = 5。
var a = [];for(let i=0;i<5;i++){ a[i] = () => { console.log(i); }}a[3](); //3
变量i是由let所宣告的所以i只对本次迴圈有效,每一次循环的i都是一个新的变量,而JaveScript引擎会记录着上一次迴圈的值并在上一次数着基础下进行计算,
不存在变量的hoisting
若使用var
来宣告变数会发生变量hoisting的现象,在变量被宣告数值之前值为undefinded
,而若是使用了let或const来宣告变数一定要在宣告数值之后才能使用否则会爆错。
//使用var宣告console.log(foo) //undefindedvar foo = 2;//使用let宣告console.log(bar) //ReferenceErrorlet bar = 2;
在使用var去宣告变数foo会发生变数hoisting的现象,因为当程式开始运行后变量foo就存在了只是尚未给予他值,所以输出为undefinded
;但若使用let来宣告则不会发生hoisting,代表在宣告他之前便量bar是不存在的。
暂时性死区(temporal dead zone)
只要在区块作用域中存在let,他所宣告的变量就会绑定这个区域
不再受外面影响,而在ES6中规定了若在区块作用域中存在let
或const
,这个区块对这些宣告的变量就形成了封闭作用域,凡是在宣告前就使用就会爆错。
var tmp = 123;if(true){ tmp = "abc" //ReferenceError let tmp; //使用let对tmp宣告会使tmp不受到外面var=123的影响}
暂时性死区对typeof影响
在过去没有块状作用域的概念下,对没有宣告的变量使用typeof去观察他的类型都会回传undefinded
,所以在没有块状作用域之前使用typeof
是绝对安全的不会爆错,而在ES6中倒入了let
与const
,在尚未使用let宣告变量之前使用typeof也会爆错。
typeof x; // ReferenceErrorlet x;
ES6所规定的暂时性死区和let,const为了减少运行时发生错误而移除了变量hoisting的情况,严格规定先宣告再使用。
不允许重複声明
let不允许在相同作用域中重複地宣告同一个变数。
//Errorfunction func() { let a = 10; var a = 1;}// Errorfunction func() { let a = 10; let a = 1;}
因此不能在函数内部重新宣告参数
func = (arg) => { let arg;};func(); //Errorfunc = (arg) => { { let arg; //因为对于let arg来说已经是第二集区块作用域,所以不符合与function相同作用域 }};func(); //不会出错
const基本介绍
const
宣告了一个唯独的常数,一旦被宣告则常数的值变不能被改变。
const PI = 3.1415;console.log(PI); //3.1415PI = 3; // Assignment to constant variable.
由于const宣告的常数值不得被改变,所以在使用const宣告一个常数的时候必须立即给予他数值(初始化)不能留到后面再赋值。
const foo; //SyntaxError: Missing initializer in const declaration
而const的作用域与let相同,只有在宣告所在的块状作用域有效。
if (true) { const MAX = 5;}MAX // Uncaught ReferenceError: MAX is not defined
const同样不支援常数的hoisting,所以同样存在暂时性死区,只能在宣告后使用。
if (true) { console.log(MAX); // ReferenceError const MAX = 5;}
const的本质
透过const所宣告的常数虽然不能更改他的值,不过他不能被更改的指的是内存的地址所保存的数据
不得被更改,对于简单类型的数据(数值、字串、Boolen),他的值就是指向const所宣告的常数的内存地址所以不得被更动,但对于複合型数据而言(物件、阵列),保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(总是指向固定的地址,数据结构不可变),但是数据结构内的值是可以改变的。
const foo = {};foo.prop = 123; //对于foo这个物件中新增属性是可以的console.log(foo.prop) // 123//但是不可将透过const宣告过的常数指向另一个物件foo = {}; //TypeError: "foo" is read-only
参考资料 :
ECMAScript 6 入门