ECMAScript6 | 特性(部分)

Posted Hugh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ECMAScript6 | 特性(部分)相关的知识,希望对你有一定的参考价值。

新特性概览

参考文章: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 | 特性(部分)的主要内容,如果未能解决你的问题,请参考以下文章

一小时学会ECMAScript6新特性

ECMAScript6 新特性

ECMAScript6相关实用特性

ECMAScript6新特性之Reflect

ECMAscript6新特性之解构赋值

ECMAScript6转码器,ES6转ES5