1. 程式人生 > >ECMAScript6 | 特性(部分)

ECMAScript6 | 特性(部分)

front script dup 結束 全部 默認值 -- 兼容 ada

新特性概覽

參考文章: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規定:
    • varfunction命令聲明的全局變量,屬於全局對象的屬性
    • letconstclass命令聲明的全局變量,不屬於全局對象的屬性
 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默認值不會生效
  • letconst明星:只要某種數據結構具有iterator接口,都可以采用數組形式解構賦值

技術分享

ECMAScript6 | 特性(部分)