新特性概覽 參考文章:http://www.cnblogs.com/Wayou/p/es6_new_features.html 這位前輩寫的很好,建議深入學習 ———————————————————————————————————————————— let命令 let命令用來聲明變數,用法類似於va ...
新特性概覽
參考文章:http://www.cnblogs.com/Wayou/p/es6_new_features.html
這位前輩寫的很好,建議深入學習
————————————————————————————————————————————
let命令
- let命令用來聲明變數,用法類似於var,但僅僅可以使用在定義的代碼塊中
- 不存在變數提升
- 暫時性死區:只要塊級作用域記憶體在let命令,它所聲明的變數就"綁定"binding這個區域,不再受外部影響
- 不允許重覆聲明:let不允許在相同作用域內重覆聲明同一個變數
test.js
1 // 在該代碼塊中聲明let,外部不能調用,花括弧之內 2 { 3 let a = 100; 4 var b = 200; 5 } 6 7 // console.log(a); 8 // 在這裡var進行了變數提升,可以在全局中使用,let不可以變數提升 9 console.log(b); 10 // ******************************************************************** 11 // 不存在變數提升 12 // ES5 13 var arr = [], 14 arrTest = []; 15 // 在迴圈中c並沒有賦給數組,而是被i迴圈覆蓋為9,所以輸出的都是9 16 for (var i = 0; i < 10; i++) { 17 var c = i; 18 arr[i] = function() { 19 return c; 20 } 21 } 22 // 遍歷執行 23 for (var i = 0; i < 10; i++) { 24 arrTest[i] = arr[i](); 25 } 26 console.log(arrTest); 27 28 // ES6 29 var arr2 = []; 30 // var c → let d 31 for (var i = 0; i < 10; i++) { 32 let d = i; 33 arr2[i] = function() { 34 return d; 35 } 36 } 37 for (var i = 0; i < 10; i++) { 38 arrTest[i] = arr2[i](); 39 } 40 console.log(arrTest); 41 // 教學視頻中沒有說清楚,那麼是否是因為let d 只對對應的代碼塊起作用,出現了10個不同的d呢? 42 // ******************************************************************** 43 // 暫時性死區 44 { 45 console.log(e); 46 let e = 100; 47 console.log(e); 48 } 49 // 在視頻中得到的結果是undefined和100,而在我的測試中第一個console.log得到的是報錯信息,提示未定義 50 // 在該代碼塊中let管轄著e,當未聲明變數e時,列印e則會提示未定義的,暫時不可以使用的 51 // ******************************************************************** 52 // 不允許重覆聲明 53 { 54 var f = 1; 55 let f = 100; 56 } 57 { 58 let g = 100; 59 var g = 1; 60 } 61 // 重覆聲明會產生報錯信息Identifier 'f' has already been declared
————————————————————————————————————————————
塊級作用域
let實際上為JavaScript新增了塊級作用域
-
在ES5中只有全局作用域和函數作用域,沒有塊級作用域,容易出現以下問題:
- 內層變數可能會覆蓋外層變數
- 用來計數的迴圈變數泄露為全局變數
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <script src="traceur.js"></script> 7 <script src="bootstrap.js"></script> 8 <!-- ES5 --> 9 <script type="text/javascript"> 10 var time = new Date(); 11 12 function f1() { 13 console.log(time); 14 if (false) { 15 var time = 'hello'; // 變數重覆聲明瞭之後,內部time會覆蓋已有變數的記憶體地址,在運行時console.log會尋找地址,此時地址還沒有存入值'hello',所以輸出為undefined 16 // time ='hello'; // 如果是使用賦值語句,則正常輸出time為Date(); 17 } 18 } 19 f1(); 20 // **************************************** 21 // 迴圈變數泄露為全局變數的問題 22 for (var i = 0; i < 12; i++) {} 23 // i跳出了迴圈體,迴圈結束後i沒有被銷毀 24 console.log(i); 25 26 // 在其他函數中也會被使用 27 function f2() { 28 console.log(i); 29 } 30 f2(); 31 // **************************************** 32 // Demo1: 33 // 第二次聲明nTest1會覆蓋第一次聲明,得到200的值 34 function f3() { 35 var nTest1 = 100; 36 if (true) { 37 var nTest1 = 200; 38 } 39 console.log(nTest1); 40 } 41 f3(); 42 // **************************************** 43 // Demo2:自調用函數 44 // 視頻演示中ES5得到的是inside,ES6得到的是outside 45 // 測試時ES5報錯,ES6正常inside 46 function fun(){ 47 console.log('i am outside'); 48 }; 49 (function (){ 50 if (false) { 51 function fun(){ 52 console.log("i am inside"); 53 }; 54 } 55 fun(); 56 })(); 57 </script> 58 <!-- ES6 --> 59 <script type="text/traceur"> 60 // **************************************** 61 // Demo1: 62 function f4() { 63 let nTest2 = 100; 64 if (true) { 65 let nTest2 = 200; 66 console.log(nTest2); 67 } 68 console.log(nTest2); 69 } 70 f4(); 71 // **************************************** 72 // Demo2:自調用函數 73 function fun(){ 74 console.log('i am outside'); 75 } 76 (function (){ 77 if (false) { 78 function fun(){ 79 console.log("i am inside"); 80 } 81 } 82 fun(); 83 }()) 84 </script> 85 </head> 86 87 <body> 88 </body> 89 90 </html>
————————————————————————————————————————————
const命令
const關鍵字聲明的是常量,不可改變
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <script src="traceur.js"></script> 7 <script src="bootstrap.js"></script> 8 <!-- ES5 --> 9 <script type="text/javascript"> 10 // const命令 11 const Pi = 3.1415; 12 console.log(Pi); 13 // 賦值的話返回錯誤信息Assignment to constant variable. 14 // Pi = 1; 15 // *********************************************************** 16 // const的塊級作用域問題 17 if (true) { 18 var a = 1; 19 } 20 // Error: a is not defined 21 // 可見const關鍵字定義的也有塊級作用域的問題 22 // console.log(a); 23 </script> 24 <!-- ES6 --> 25 <script type="text/traceur"> 26 // 暫時性死區 27 if (true) { 28 console.log(b); 29 const b = 2; 30 } 31 // *********************************************************** 32 { 33 //Error:["file:///F:/6.Code/Front-End/JavaScript/Test/index_inline_script_1.js:6:16: Duplicate declaration, c"] 34 //不可重覆聲明 35 //var c=200; 36 const c = 300; 37 console.log(c); 38 } 39 // *********************************************************** 40 // 通過const聲明對象時,顯示這個對象是只讀的,該對象是凍結狀態的,但仍然可以寫入值 41 const person = {}; 42 person.name = "hello"; 43 console.log(person); 44 person.name = "hugh"; 45 console.log(person); 46 console.log(Object.isSealed()); 47 console.log(Object.isFrozen()); 48 // 如果以凍結方法定義的對象,則是無法寫入的 49 const person2 = Object.freeze({}); 50 person2.name = "hugh"; 51 person2.age = 21; 52 console.log(person2); 53 console.log(person2.name); 54 console.log(person2.age); 55 console.log(Object.isFrozen()); 56 // 正確的const凍結對象的方法 57 const person3 = Object.freeze({ 58 name: 'hhh', 59 age: 1 60 }); 61 console.log(person3); 62 console.log(Object.isFrozen()); 63 // *********************************************************** 64 // const聲明的數組可以數組操作,但不可以整體賦值,視為重新定義 65 const arr1 = []; 66 arr1.push(1); 67 arr1.push(2); 68 console.log(arr1); 69 arr1.pop(); 70 console.log(arr1); 71 console.log(arr1.length); 72 //Error:["file:///F:/6.Code/Front-End/JavaScript/Test/index_inline_script_1.js:30:5: arr1 is read-only"] 73 //arr1 = ['a','b','c']; 74 //console.log(arr1); 75 // *********************************************************** 76 // 徹底凍結對象,請對比參考JavaScript中的遞歸凍結函數方法 77 var constantize = (obj) => { 78 Object.freeze(obj); 79 Object.keys(obj).forEach((key,value)=>{ 80 if(typeof obj[key]==='object'{ 81 constantize(obj[key]); 82 }); 83 }); 84 }; 85 </script> 86 </head> 87 88 <body> 89 </body> 90 91 </html>
————————————————————————————————————————————
跨模塊常量
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <script src="traceur.js"></script> 7 <script src="bootstrap.js"></script> 8 <!-- ES5 --> 9 <script type="text/javascript"> 10 11 </script> 12 <!-- ES6 --> 13 <script type="text/traceur"> 14 // module.js, 在這裡將變數輸出 15 export const cVariantName = "111"; 16 export const iVariantName = 3; 17 export const fVariantName = 4.111; 18 19 // use.js, 在這裡將變數全部引入 20 import * as variant from './module.js'; 21 console.log(variant.cVariantName); // 輸出"111"; 22 console.log(variant.iVariantName); // 輸出3; 23 console.log(variant.fVariantName); // 輸出4.111; 24 25 // otherUse.js, 引入部分變數 26 import {iVariantName,fVariantName} as variant from './module.js'; 27 console.log(variant.iVariantName); // 輸出3; 28 console.log(variant.fVariantName); // 輸出4.111; 29 30 // onlyUse.js, 只引入一個變數 31 import iVariantName as variant from './module.js'; 32 console.log(variant.iVariantName); // 輸出3; 33 </script> 34 </head> 35 36 <body> 37 </body> 38 39 </html>
————————————————————————————————————————————
全局對象屬性
- 全局變數是最頂層的對象
- 瀏覽器環境指的是window對象
- Node.js指的是global對象
-
在JavaScript中所有全局變數都是全局對象的屬性
p.s.在Node中這一條只對REPL環境使用,模塊環境必須顯式聲明成global屬性
-
ES6規定:
- var、function命令聲明的全局變數,屬於全局對象的屬性
- let、const、class命令聲明的全局變數,不屬於全局對象的屬性
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <script src="traceur.js"></script> 7 <script src="bootstrap.js"></script> 8 <!-- ES5 --> 9 <script type="text/javascript"> 10 11 </script> 12 <!-- ES6 --> 13 <script type="text/traceur"> 14 var varName = "varValue"; 15 // 瀏覽器環境 16 console.log(window.varName); // 輸出varValue 17 // Node環境 18 // console.log(global.varName); 19 // 通用環境 20 console.log(this.varName); // 輸出varValue 21 22 let letName = "letValue"; 23 console.log(window.letName); // 相容模式:letValue, 嚴格模式:undefined 24 console.log(this.letName); // 相容模式:letValue, 嚴格模式:undefined 25 </script> 26 </head> 27 28 <body> 29 </body> 30 31 </html>
————————————————————————————————————————————
解構賦值 Dustructuring
- 解構:ES6允許按照一定模式,從數組和對象中提取值,對變數進行賦值
- 不完全解構:等號左邊的模式只匹配一部分等號右邊的數組
- 指定預設值:ES6內部使用嚴格相等運算符===來判斷一個位置是否有值,如果數組成員不嚴格等於undefined預設值不會生效
- let和const明星:只要某種數據結構具有iterator介面,都可以採用數組形式解構賦值