最近用淘寶的weex做了個項目,最近稍微閑下來了。正好很久沒有接觸RN了,所以趁這個機會系統的學習一下ES6的相關知識。
孔子說:沒有對比就沒有傷害。所以我們要拿ES6和ES5好好對比的學習。這樣才能明白es6是多少的好,積極的擁抱她!
1.let
用let聲明的變量,只會在let命令所在的代碼塊內有效。
let的塊狀作用域
我們來看一個簡單的例子:
'use strict'; { let name = 'cloud'; var age = 21; } name;//ReferenceError: name is not defined age;//21
我們在let聲明變量name的代碼塊之外去訪問這個變量,結果name是沒有定義的。如果我們希望在能訪問到name應該怎么做呢?
'use strict'; { let name = 'cloud'; var age = 21; name;//cloud }
沒錯,我們在let聲明變量的代碼塊中去訪問name變量。結果也正如我們期望的那樣,name的值被訪問到了。對於高級oo語言而言,他們都是基於塊狀作用域的。
所以說,let讓我們聲明的變量也擁有了塊狀作用域這樣一個概念,而不僅僅是函數作用域了。
既然有了塊級作用域,那把let用來聲明循環里的變量是極好的。
'use strict'; //死循環 for(var i = 0; i < 5; i++){ console.log(i); for(var i = 0; i < 3; i++){ console.log(i); } } for(let i = 0; i < 5; i++){ console.log(i); for(let i = 0; i < 3; i++){ console.log(i); } }
如果沒有let的話,上面代碼中的內循環每次都會把var聲明的變量i重置為0,所以毫無疑問,這是一個死循環。所以我們必須把內循環中變量i換成變量j,或者其他的名稱。但是這也會帶來一個副作用,就是循環完成以后的i,被泄露成了全局變量。
'use strict'; for(var i = 0; i < 5; i++){ i;//0,1,2,3,4 } i;//5 for(let i = 0; i < 5; i++){ i;//0,1,2,3,4 } i;//ReferenceError: i is not defined
let聲明的變量不存在變量聲明提升
'use strict'; name; //undefined age; //ReferenceError: age is not defined var name = 'cloud'; let age = 21;
用var聲明的變量name,雖然我們在name使用后才聲明並給其賦值,但是因為變量聲明提升的原因,我們看到name已經聲明了,只是其值是undefined而已。但是用let聲明的age變量,卻沒有定義。所以說let是不存在變量聲明提升的。
let的暫時性死區(temporal dead zone,簡稱TDZ)
只要是塊級作用域中存在let命令,它所在的區域就成為了暫時性死區,使用let命令聲明變量之前,該變量都是不可用的。同時該變量不再受到外部的影響。
var name = 'new cloud';
{ //TDZ start name = 'cloud'; name;//ReferenceError: name is not defined let name; //TDZ end name;//undefined let name = 'cloud'; name;//cloud }
如上代碼,在let聲明name之前,那么這個變量都是不可用的。所以這也帶來一個問題,當我們使用typeof這樣的反射機制來檢測我們的所需的變量是否按照我們設想的那樣,typeof不再是一個堅定不移的忠臣了,它也會報錯了。
{ typeof name;//undefined var name = 'cloud'; typeof name;//ReferenceError: name is not defined let name = 'cloud'; }
let塊狀作用域內聲明的變量,不允許重復聲明。
1.
'use strict'; var name = 'cloud'; var name = 'new cloud'; name;//new cloud
2.
'use strict'; { let name = 'cloud'; var name = 'new cloud'; name; let name = 'cloud'; var name = 'new cloud'; name; let name = 'cloud'; let name = 'new cloud'; name; //SyntaxError: Identifier 'name' has already been declared }
第二段代碼中的所有聲明方式,都會報錯。name已經被聲明。
'use strict'; function setName(name){ let name = name;//SyntaxError: Identifier 'name' has already been declared { let name = 'new cloud'; console.log(name);//new cloud } console.log(name);//cloud } setName('cloud');
同樣,在函數中重新聲明變量也會報錯的。
2.const
const是一個只讀的常量。一旦聲明,就不可更改。
'use strict'; const PI = 3.14; PI = 3.1415;//TypeError: Assignment to constant variable
如果用const聲明了常量,但是並沒有去初始化它。那么,也是會報錯的。
'use strict'; const PI;//SyntaxError: Missing initializer in const declaration
同樣,const
的作用域與let
命令相同:只在聲明所在的塊級作用域內有效。const
命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置后面使用。const
聲明的常量,也與let
一樣不可重復聲明。
如果我們用const來聲明一個引用類型的話。const只能保證指針域不變,但是並不能保證數據域是不可變更的。
'use strict'; const employee = {}; employee['name'] = 'cloud'; employee['age'] = 21; employee = {}; //TypeError: "employee " is read-only employee['name'] = 'new cloud'; console.log(employee.name);//new cloud
如果想把一個對象完成的凍結的話,應該是用Object.freeze()方法。
const employee = Object.freeze({}); employee.name= 'cloud';//TypeError: Can't add property prop, object is not extensible