WPS JSA 宏編程(JS):2.對各版本 ES 特性的支持


一、支持大部分 ES6 特性

1.class

下面是關於 ES6 引入的經典類的試驗代碼:

  1 /*參數類型異常 :用於封裝參數類型異常信息*/
  2 class ParameterTypeError extends Error {
  3     constructor(paramName, paramType) {
  4         if (!(typeof paramName == 'string'))
  5             throw new ParameterTypeError('paramName', String);
  6         if (!(paramType instanceof Function))
  7             throw new ParameterTypeError('paramType', Function);
  8         let msg = 'Parameter "' + paramName +
  9             '" must be a ' + paramType.name +
 10             ' object.';
 11         super(msg);
 12         this.ParameterName = paramName;
 13         this.ParameterType = paramType;
 14     }
 15     toString() {
 16         return ParameterTypeError.name + ' : ' + this.message;
 17     }
 18     static check(param, paramName, paramType) {
 19         if (!((param instanceof paramType) ||
 20             (typeof param == paramType.name.toLowerCase())))
 21             throw new ParameterTypeError(paramName, paramType);
 22     }
 23 }
 24 class Point {
 25     constructor(x, y) {
 26         ParameterTypeError.check(x, 'x', Number);
 27         ParameterTypeError.check(y, 'y', Number);
 28         this.x = x;
 29         this.y = y;
 30         Point.count++;
 31     }
 32     static get count() {
 33         if (Point._count == undefined)
 34             Point._count = 0;
 35         return Point._count;
 36     }
 37     static set count(value) {
 38         if (Point._count == undefined)
 39             Point._count = 0;
 40         Point._count = value;
 41     }
 42     static get Version() {
 43         return '2D';
 44     }
 45     toString() {
 46         return '(' + this.x + ', ' + this.y + ')';
 47     }
 48     distanceTo(p) {
 49         ParameterTypeError.check(p, 'p', Point);
 50         return Math.sqrt(
 51             Math.pow(this.x - p.x, 2) +
 52             Math.pow(this.y - p.y, 2));
 53     }
 54     static distanceBetween(p1, p2) {
 55         ParameterTypeError.check(p1, 'p1', Point);
 56         ParameterTypeError.check(p2, 'p2', Point);
 57         return Math.sqrt(
 58             Math.pow(p1.x - p2.x, 2) +
 59             Math.pow(p1.y - p2.y, 2));
 60     }
 61 }
 62 class NamedPoint extends Point {
 63     constructor(name, x, y) {
 64         ParameterTypeError.check(name, 'name', String);
 65         super(x, y);
 66         this._name = name;
 67     }
 68     get name() {
 69         return this._name;
 70     }
 71     toString() {
 72         return this._name + super.toString();
 73     }
 74 }
 75 function classTest() {
 76     let p = new Point(3, 4);
 77     Console.log('p = ' + p);
 78     let np = new NamedPoint("ShotTarget", 6, 8);
 79     Console.log('np = ' + np);
 80     //為只讀屬性賦值是無效的,但也不報錯
 81     np.name = "WTF";
 82     Console.log('np = ' + np);
 83     Console.log('np.name = ' + np.name);
 84     Console.log('p.distanceTo(np) = ' + p.distanceTo(np));
 85     Console.log('instance count : ' + Point.count);
 86     //靜態方法,會被子類繼承
 87     Console.log(NamedPoint.distanceBetween(np, p));
 88     //實例方法,會被子類繼承
 89     Console.log(np.distanceTo(p));
 90     //靜態屬性
 91     Console.log('static property Version : ' + Point.Version);
 92     //靜態屬性,會被子類繼承
 93     Console.log(NamedPoint.count);
 94     //自定義異常
 95     try {
 96         p.distanceTo(33);
 97     } catch(e) {
 98         Console.log(e.message);
 99         Console.log(e);
100     }
101 }

其輸出如下:

p = (3, 4) np = ShotTarget(6, 8) np = ShotTarget(6, 8) np.name = ShotTarget p.distanceTo(np) = 5 instance count : 2 5 5 static property Version : 2D 2 Parameter "p" must be a Point object. ParameterTypeError : Parameter "p" must be a Point object.

2.Proxy

  1 //居中填充
  2 String.prototype.padCenter = 
  3   function(targetLength, padString = ' ') {
  4   if (typeof targetLength != 'number')
  5     throw new TypeError('Parameter "targetLength" ' +
  6                         'must be a number object.');
  7   if (typeof padString != 'string') {
  8     if (padString === null)
  9       padString = 'null';
 10     else
 11       padString = padString.toString();
 12   }
 13   let padStrWidth = padString.length;   
 14   if (padStrWidth == 0) return this;
 15   let restWidth = targetLength - this.length;
 16   if (restWidth <= 0) return this;
 17   let leftWidth = Math.trunc(restWidth / 2);
 18   let rightWidth = leftWidth + restWidth % 2;
 19   if (padString.length == 1) {
 20     return padString.repeat(leftWidth) + this + 
 21       padString.repeat(rightWidth);
 22   } else {
 23     if (leftWidth == 0)
 24       return this + padString[0];
 25     else {
 26       //leftPart
 27       let leftRepeat = Math.trunc(leftWidth / padStrWidth); 
 28       let leftRest = leftWidth - leftRepeat * padStrWidth;  
 29       let leftStr = padString.repeat(leftRepeat) +
 30           padString.substr(0, leftRest);
 31       //rightPart
 32       let rightRepeat = Math.trunc(rightWidth / padStrWidth);
 33       let rightRest = rightWidth - rightRepeat * padStrWidth;
 34       let rightStr = padString.repeat(rightRepeat) +
 35           padString.substr(0, rightRest);
 36       return leftStr + this + rightStr;
 37     }
 38   }
 39 }
 40 /*Proxy handler 可對應於
 41   Reflect.apply()
 42   Reflect.construct()
 43   Reflect.defineProperty()
 44   Reflect.deleteProperty()
 45   Reflect.get()
 46   Reflect.getOwnPropertyDescriptor()
 47   Reflect.getPrototypeOf()
 48   Reflect.has()
 49   Reflect.isExtensible()
 50   Reflect.ownKeys()
 51   Reflect.preventExtensions()
 52   Reflect.set()
 53   Reflect.setPrototypeOf()
 54   實現想要的代理
 55 */
 56 class ES6ProxyTest {
 57     //既然 Reflect.set(target, key, value[, receiver]) 有
 58     //要設置的屬性的鍵和值,我們就可以通過 set 代理,在一個
 59     //對象的定義的外部:
 60     //1.通過鍵,攔截對某些屬性的寫入
 61     //2.通過值,檢驗類型,攔截非法寫入
 62     //3.通過鍵,重定向屬性的寫入,就像為屬性設置一些假名一樣
 63     static SetProxy() {
 64         let p = new Point(3, 8);
 65         let pp = new Proxy(p, {
 66             set:function(target, key, value, receiver){
 67                 //Reflect.set(target, key, value[, receiver])
 68                 //target : 用於接收屬性(被代理的對象)的對象
 69                 //key : 要寫入的屬性的鍵(字符串或Symbol類型)
 70                 //value : 要寫入的屬性新值
 71                 //receiver : 如果 target 對象的 key 屬性有 setter,
 72                 //         receiver 則為 setter 調用時的 this 值。
 73                 //return : 返回一個 Boolean 值,表明操作的成敗
 74                 let success = Reflect.set(target, key, value, receiver);
 75                 if (success) {
 76                     //Console 在此不可用
 77                     Debug.Print('property '+ key +' on '+ 
 78                         target + ' set to '+ value);
 79                 }
 80                 //必須返回操作成敗狀態,否則報錯
 81                 return success;
 82             }
 83         });
 84         pp.xxx = 13;
 85         Console.log(p.xxx);
 86     }
 87     
 88     //既然 Reflect.get(target, key[, receiver]) 提供了要讀取
 89     //的屬性的鍵,我們就可以通過 get 代理,在對象的定義的外部:
 90     //1.通過鍵,攔截對某些屬性的讀取
 91     //2.通過鍵,偽造一些不存在的屬性
 92     //3.通過鍵,實現類同假名的屬性
 93     static GetProxy() {
 94         var obj = new Proxy({}, {
 95           get: function (target, key, receiver) {
 96             //Console 在此不可用
 97             Debug.Print(`getting ${key}!`);
 98             //Reflect.get(target, key[, receiver])
 99             //target : 被代理的對象
100             //key : 要讀取的屬性的鍵(字符串或Symbol類型)
101             //receiver : 如果 target 對象的 key 屬性有 getter, 
102             //           receiver 則為 getter 調用時的 this 值。
103             //return : 屬性的值。
104             return Reflect.get(target, key, receiver);
105           }
106         });
107         obj.count = 1;
108         ++obj.count;
109     }
110     
111     /*Reflect.apply(target, thisArg, argsList)
112       target : 被代理對象,請確保它是一個 Function 對象
113       thisArg : 函數調用時綁定的對象
114       argsList : 函數調用時傳入的實參列表,該參數應該是一個類數組的對象。
115       return : 調用函數返回的結果
116       通過這種代理:
117       1.檢驗調用時傳入的參數
118       2.阻止函數被調用
119     */
120     static ApplyProxy() {
121         function sum (...values){
122             return values.reduce((pre, cur) => pre + cur, 0);
123         }
124         let sumProxy = new Proxy(sum, {
125             apply : function(target, thisArg, argsList){
126                 argsList.forEach(arg => {
127                     if(typeof arg !== "number")
128                         throw new TypeError("所有參數必須是數字,親!");
129                 });
130                 return Reflect.apply(target, thisArg, argsList);
131             }
132         });
133         
134         try {
135             let r = sumProxy(3, 5, 'hello');
136             Console.log(r);
137         } catch(e) {
138             Console.log(e.message);
139         }
140         Console.log(sumProxy(3, 8, 5));
141     }
142     
143     /*Reflect.construct(target, argsList[, newTarget])
144       target : 被運行的目標構造函數
145       argsList : 類數組,目標構造函數調用時的參數。
146       newTarget : 可選,作為新創建對象的原型對象的 constructor 屬性,
147                   參考 new.target 操作符,默認值為 target。      
148     */
149     static ConstructProxy() {
150         function sum (...values){
151             return values.reduce((pre, cur) => pre + cur, 0);
152         }
153         let sumProxy = new Proxy(sum, {
154             construct:function(target, argsList){
155                 throw new TypeError("親,該函數不能通過 new 調用。");
156             }
157         });
158         
159         try {
160             let x = new sumProxy(3, 5, 7);
161         } catch(e) {
162             Console.log(e.message);
163         }
164     }
165     
166     //禁止向指定單元格區域寫入數據
167     static ForbidSetValue() {
168         let rng = new Range('B1:D3');
169         rng.Value2 = 32;
170         
171         let rngProxy = new Proxy(rng, {
172             set : function(target, key, value, receiver) {
173                 if (key === 'Value2') {
174                     throw new Error('無法設置屬性')
175                 } else
176                     return Reflect.set(target, key, value, receiver);
177             }
178         });
179         
180         try {
181             rngProxy.Value2 = 168;
182         } catch(e) {
183             Console.log(e.message);
184         }
185         Console.log(rngProxy.Text);
186     }
187     
188     //運行所有測試用例
189     static RunAll() {
190         let members = Object.getOwnPropertyNames(ES6ProxyTest);
191         let notCall = ['length', 'prototype', 'name', 'RunAll'];
192         for (let member of members) {
193             if (!notCall.includes(member)) {
194                 Console.log(member.padCenter(56, '-'));
195                 eval(`ES6ProxyTest.${member}()`);
196             }
197         }
198     }
199 }

在立即窗口中輸入 ES6ProxyTest.RunAll(); ,然后回車,其輸出如下:

------------------------SetProxy------------------------ property xxx on (3, 8) set to 13 13 ------------------------GetProxy------------------------ getting count! -----------------------ApplyProxy----------------------- 所有參數必須是數字,親! 16 ---------------------ConstructProxy--------------------- 親,該函數不能通過 new 調用。 ---------------------ForbidSetValue--------------------- 無法設置屬性 32

二、實測支持到 ES2019

0.示例代碼運行環境的設置代碼

因為使用了全局表達式,請將【工具】》【選項】》【編譯】》【禁止全局作用域表達式】取消勾選

  1 //獲取字符串位寬(即字符串占的字符寬度)
  2 String.prototype.byteWidth = function() {
  3     var length = 0;
  4     Array.from(this).map(function(char){
  5         //字符編碼大於255,說明是雙字節字符
  6         if (char.charCodeAt(0) > 255) {
  7             length += 2;
  8         } else {
  9             length++;
 10         }
 11     });
 12     
 13     return length;
 14 };
 15 
 16 {/*Console 對象的增強*/
 17     //控制台默認分隔線字符
 18     Console.__proto__.DefaultSepLineSepChar = '-';
 19     //控制台默認的分隔線寬度
 20     Console.__proto__.DefaultSepLineWidth = 56;
 21     
 22     //向控制台輸出分隔線
 23     Console.__proto__.PrintSepLine =
 24         function(byteWidth, sepChar) {
 25         if (sepChar == undefined)
 26             sepChar = this.DefaultSepLineSepChar;
 27         else
 28             sepChar = sepChar.toString()[0];
 29         
 30         if (byteWidth == undefined)
 31             byteWidth = this.DefaultSepLineWidth;
 32             
 33         if (typeof byteWidth != 'number' ||
 34             byteWidth < 0)
 35             throw new Error('byteWidth 必須是非負數');
 36         else
 37             byteWidth = Math.floor(byteWidth);
 38         
 39         let sepLine;
 40         if (sepChar.byteWidth() == 1)
 41             sepLine = sepChar.repeat(byteWidth);
 42         else
 43             sepLine = sepChar.repeat(byteWidth / 2);
 44             
 45         Console.log(sepLine);
 46     };
 47     
 48     //向控制台輸出分隔線
 49     Console.__proto__.PrintNamedSepLine =
 50         function(name, byteWidth, sepChar) {
 51         if (name == undefined)
 52             throw new Error('必須提供 name 參數');
 53         else 
 54             name = name.toString()
 55                 .replace('\n', '')
 56                 .replace('\r', '');
 57         if (sepChar == undefined)
 58             sepChar = this.DefaultSepLineSepChar;
 59         else
 60             sepChar = sepChar.toString()[0];
 61         
 62         if (byteWidth == undefined)
 63             byteWidth = this.DefaultSepLineWidth;
 64             
 65         if (typeof byteWidth != 'number' ||
 66             byteWidth < 0)
 67             throw new Error('byteWidth 必須是非負數');
 68         else
 69             byteWidth = Math.floor(byteWidth);
 70         
 71         let sepLine = name;
 72         let selfWidth = name.byteWidth();
 73         if (byteWidth > selfWidth) {
 74             let restWidth = byteWidth - selfWidth;
 75             let leftPadWidth = Math.floor(restWidth / 2);
 76             let rightWidth = Math.floor(restWidth / 2) +
 77                 restWidth % 2;
 78             if (sepChar.byteWidth() == 1)
 79                 sepLine = sepChar.repeat(leftPadWidth) +
 80                     sepLine + sepChar.repeat(rightWidth);
 81             else
 82                 sepLine = sepChar.repeat(leftPadWidth / 2) +
 83                     sepLine + sepChar.repeat(rightWidth /2);
 84         }
 85             
 86         Console.log(sepLine);
 87     };  
 88     
 89     //向控制台一次輸出多個值,避免手動拼接字符串
 90     Console.__proto__.WriteAll = function() {
 91         if (arguments.length == 0) return;
 92         let info = Array.prototype.map
 93             .call(arguments, v => {
 94                 if (v === null)
 95                     return 'null';
 96                 else if(v === undefined)
 97                     return 'undefined';
 98                 else
 99                     return v.toString();
100             })
101             .join('; ');
102         Console.log(info);
103     };
104     
105     //向控制台作講述式輸出
106     Console.__proto__.Tell = function(description, value) {
107         if (value === null)
108             Console.log(description + ' : null');
109         else if (value === undefined)
110             Console.log(description + ' : undefined');
111         else
112             Console.log(description + ' : ' + value.toString());
113     };  
114 }

1.ES2016_ES7 特性測試

 1 function ES2016_ES7() {
 2     //ES2016 只添加了兩個功能:
 3     let arr = [1, 2, 3];
 4     //1. Array.prototype.includes()
 5     if (typeof arr.includes == 'function') {
 6         Console.Tell('arr.includes(2)', arr.includes(2));
 7         Console.Tell('arr.includes(31)', arr.includes(31));
 8     }
 9     //2. 指數運算符
10     Console.Tell('3**3', 3**3);
11 }

2.ES2017_ES8 特性測試

 1 function ES2017_ES8() {
 2     let obj = { one : 1, two : 2, three : 3 };
 3     //1.Object.values() 獲取對象的所有屬性值
 4     Console.PrintNamedSepLine('Object.values(obj)');
 5     if (typeof Object.values == 'function') {
 6         let values = Object.values(obj);
 7         Console.log(values instanceof Array);
 8         Console.log(values.toString());
 9     }
10     
11     //2.Object.entries() 獲取對象的屬性名-值對
12     Console.PrintNamedSepLine('Object.entries(obj)');
13     if (typeof Object.entries == 'function') {
14         let entries = Object.entries(obj);
15         Console.log(entries instanceof Array);
16         Console.log(entries[0] instanceof Array);
17         Console.log(entries[0][0] + ' : ' + entries[0][1]);
18         for (let [k, v] of entries)
19             Console.log(k + ' => ' + v);
20     }
21     
22     //3.Object.getOwnPropertyDescriptors() 獲取一個對象的所有自身屬性的
23     //  描述符。屬性描述符(property descriptor)對象:
24     //value:就是屬性的值,默認 undefined
25     //writable:決定屬性能否被賦值
26     //get:訪問器函數(getter),函數或 undefined,在取屬性值時被調用
27     //set:設置器函數(setter),函數或 undefined,在設置屬性值時被調用
28     //enumerable:決定 for in 或 Object.keys 能否枚舉該屬性
29     //configurable:決定該屬性能否被刪除,以及除 value 和 writable 外的
30     //              其他特性是否可以被修改
31     Console.PrintNamedSepLine('Object.getOwnPropertyDescriptors(obj)');
32     if (typeof Object.getOwnPropertyDescriptors == 'function') {
33         let x = Object.getOwnPropertyDescriptors(obj);
34         Console.Tell('Object.getOwnPropertyDescriptors(obj)', x);
35     }
36     
37     //4.String.prototype.padStart()/padEnd() 字符串左/右填充
38     Console.PrintNamedSepLine('String.padStart/padEnd');
39     if (typeof String.prototype.padStart === 'function' &&
40         typeof String.prototype.padEnd == 'function') {
41         let str = 'hello';
42         Console.log(str.padStart(10, '+'));
43         Console.log(str.padEnd(10, '-'));               
44     }
45     
46     //5.結尾逗號,對象定義、數組定義和函數參數列表等等
47     Console.PrintNamedSepLine('尾逗號');
48     {
49         let gift = {
50             Name : 'Computer',
51             Price : 5000,
52             Color : 'black',
53         };
54         Console.log(JSON.stringify(gift));
55         let exGrilFriends = [
56             'Lily Morgen',
57             'John Smith',
58             'Kate William',
59         ];
60         Console.log(exGrilFriends.toString());
61         let func = function(
62             firstPartNumber,
63             secondPartNumber,
64             ) { Console.log(firstPartNumber + '/' + secondPartNumber); }
65         func(321, 123);
66     }
67     
68     //6.ShareArrayBuffer ...
69 }

3.ES2018_ES9 特性測試

 1 function ES2018_ES9() {
 2     {//1.剩余參數
 3         Console.PrintNamedSepLine('剩余參數');
 4         let func = function(a, b, ...rest) {
 5             let sum = a + b;
 6             if (rest.length == 0)
 7                 return sum;
 8             else {
 9                 for (let x of rest) 
10                     sum += x;
11                 return sum;
12             }
13         };
14         Console.log(func(1, 2));
15         Console.log(func(1, 2, 3));
16         Console.log(func(1, 2, 3, 4));
17     }
18     
19     {//2.正則表達式 s 模式,dotAll,即包含換行符
20         Console.PrintNamedSepLine('正則表達式 s 模式');
21         let isMatch = /hello.es9/.test('hello\nes9');
22         Console.log(isMatch);
23         isMatch = /hello.es9/s.test('hello\nes9');
24         Console.log(isMatch);
25     }
26     
27     {//3.正則之命名捕獲組
28         Console.PrintNamedSepLine('正則之命名捕獲組');
29         let str = "Jim is 12."; 
30         let re = /(?<name>\w+) is (?<age>\d+)/;
31         let matches = re.exec(str);
32         Console.log(matches.toString());
33         for (let ppt in matches) 
34             Console.log(ppt);
35         Console.log(matches.groups);
36         for (let ppt in matches.groups)
37             Console.log(ppt);
38         Console.log('age is ' + matches.groups['age']); 
39     }
40     
41     {//4.正則表達式之反向斷言
42         Console.PrintNamedSepLine('正則表達式之反向斷言');
43         let s = 'he is 12 years old. he has 3 cars.';
44         //4.1.右匹配斷言 : (?=...)
45         Console.log('4.1 => ' + s.match(/\d+(?= cars)/));
46         //4.2.右不匹配斷言 : (?!...)
47         Console.log('4.2 => ' + s.match(/\d+(?! cars)/));
48         //4.3.左匹配斷言 : (?<=...)
49         Console.log('4.3 => ' + s.match(/(?<=has )\d+/));
50         //4.2.左不匹配斷言 : (?<!...)
51         Console.log('4.4 => ' + s.match(/(?<!has )\d+/));
52     }   
53     
54     
55     {//5.正則表達式 u 模式,即字符集模式,支持\p{字符集名},
56     //  或\P{字符集名}形式匹配...
57         Console.PrintNamedSepLine('正則表達式 u 模式')
58         let re = /\p{White_Space}+/u;
59         let wsStrs = ['\n', '\r', ' ', '\n\r'];
60         wsStrs.forEach(x => Console.log(re.test(x)));
61     }
62     
63     //6.async/await...
64     //7.promise.finally...
65 }

4.ES2019_ES10 特性測試

 1 function ES2019_ES10 () {
 2     //1.Object.fromEntries() 從對象的屬性名值對數組轉換回對象,
 3     //  與 Object.entries() 功能相反;NA
 4     Console.PrintNamedSepLine('Object.fromEntries');
 5     if (typeof Object.fromEntries == 'function') {
 6         let obj = { one : 1, two : 2, three : 3 };
 7         let entries = Object.entries(obj);
 8         let objSame = Object.fromEntries(entries);
 9         Console.log(objSame);
10     }
11     
12     //2.Array.prototype.flat 將數組打平
13     Console.PrintNamedSepLine('Array.prototype.flat([depth])');
14     if (typeof Array.prototype.flat === 'function') {
15         Console.Tell('[1, [2, 3]].flat()', JSON.stringify(
16             [1, [2, 3]].flat()));
17         Console.Tell('[1, [2, 3, [1]]].flat()', JSON.stringify(
18             [1, [2, 3, [1]]].flat()));
19         Console.Tell('[1, [2, 3, [1]]].flat(2)', JSON.stringify(
20             [1, [2, 3, [1]]].flat(2)));
21     } 
22     
23     //3.Array.prototype.flatMap 類同於 Linq-SelectMany
24     Console.PrintNamedSepLine('Array.prototype.flatMap');
25     if (typeof Array.prototype.flatMap === 'function') {
26         Console.Tell('[1, [2, 3]].flatMap(x => x)', JSON
27             .stringify([1, [2, 3]].flatMap(x => x)));
28         let strs = ['Jobs Steven', 'is', 'great'];
29         let elementProcessor = x => x.split(' ');
30         Console.log(JSON.stringify(strs) + '.flatMap(' +
31             elementProcessor.toString() + ') :\n' +
32             JSON.stringify(strs.flatMap(elementProcessor)));
33         Console.log('[1, 2, 3].map(x => [x * 2]) :\n' +
34             JSON.stringify([1, 2, 3].map(x => [x * 2])));
35         Console.log('[1, 2, 3].flatMap(x => [x * 2]) :\n' +
36             JSON.stringify([1, 2, 3].flatMap(x => [x * 2])));
37     }
38     
39     //4.String.prototype.trimStart/trimEnd
40     Console.PrintNamedSepLine('String.prototype.trimStart/trimEnd');
41     if (typeof String.prototype.trimStart === 'function' &&
42         typeof String.prototype.trimEnd === 'function') {
43         let s = '   yes  ';
44         Console.log(JSON.stringify(s) + '.trimStart() = ' +
45             JSON.stringify(s.trimStart()));
46         Console.log(JSON.stringify(s) + '.trimEnd() = ' +
47             JSON.stringify(s.trimEnd()));
48     }
49     
50     //5.Symbol.protoype.description
51     Console.PrintNamedSepLine('Symbol.protoype.description');
52     if (Symbol.iterator.description != undefined) {
53         Console.log('Symbol.iterator.description = ' +
54             Symbol.iterator.description);
55     }
56     
57     //6.Array.prototype.sort([compareFunction]) : 增加了一個參數
58     //  可以按照指定規則排序,而不是默認的將元素字符串化后排序
59     Console.PrintNamedSepLine('Array.prototype.sort([compareFunction])');
60     {
61         let names = ['Joe Smith', 'Jobs Steven', 'Bill Gates'];
62         let compFunc = (a, b) => a.length - b.length;
63         Console.log(JSON.stringify(names));
64         names.sort(compFunc);
65         Console.log(JSON.stringify(names));
66     }
67 }

5.ES2020_ES11 特性測試

 1 function ES2020_ES11() {
 2     //1.鏈式判斷運算符;NA
 3     Console.PrintNamedSepLine('鏈式判斷運算符');
 4     try {   
 5         let obj = { one : 1, two : 2, three : 3 };
 6         //直接寫下面這句會編譯不過,所以在這兒用 eval
 7         //Console.log(obj?.yes?.toExponential());   
 8         eval('Console.log(Math?.dk?.good == undefined)');
 9     } catch { Console.log('Nonsupport'); }
10     
11     //2.String.prototype.matchAll
12     Console.PrintNamedSepLine('String.prototype.matchAll')
13     if (typeof String.prototype.matchAll == 'function') {
14         let regex = /t(e)(st(\d?))/g;
15         let string = 'test1test2test3';
16         let allMatches = [...string.matchAll(regex)];
17         Console.log(allMatches.toString());
18     }
19     
20     //3.Null判斷運算符 : 如果左值是 null/undefined,使用右值
21     Console.PrintNamedSepLine('Null判斷運算符');
22     try {
23         let x = eval('ksdfksk ?? false');
24         Console.log(x);
25     } catch { Console.log('Nonsupport'); }
26     
27     //4.Bigint : 新增類型
28     Console.PrintNamedSepLine('Bigint 類型');
29     Console.log('是否支持 Bigint 類型?:' + 
30         (typeof Bigint != 'undefined'));
31         
32     //5.Promise.*...
33     //6.import ...
34     //7.export ...
35 }

6.ES2021_ES12 特性測試

 1 function ES2021_ES12() {
 2     //1.復合邏輯賦值運算符:??=/&&=/||=
 3     Console.PrintNamedSepLine('復合邏輯賦值運算符');
 4     try {
 5         //以下相當於 let xx = xx ?? 1;
 6         //即,如果 xx == null/undefined, 賦值為 1
 7         let x = eval('let xx ??= 1; xx;');
 8         Console.log(x);
 9     } catch { Console.log('Nonsupport'); }
10     try {
11         //以下相當於 let yy = yy && true;
12         let y = eval('let yy &&= true; yy;');
13         Console.log(y);
14     } catch { Console.log('Nonsupport'); }
15     try {
16         //以下相當於 let zz = zz || true;
17         let z = eval('let zz ||= true; zz;');
18         Console.log(z);
19     } catch { Console.log('Nonsupport'); }
20     
21     //2.數字分隔符
22     Console.PrintNamedSepLine('數字分隔符');
23     try {
24         let num = eval('1_5000');
25         Console.log(num);
26     } catch { Console.log('Nonsupport'); }
27     
28     //3.String.prototype.replaceAll
29     Console.PrintNamedSepLine('String.prototype.replaceAll');
30     if (typeof String.prototype.replaceAll === 'function') {
31         Console.log("'hello world'.replaceAll('o', '_') :" +
32             'hello world'.replaceAll('o', '_'));
33     }
34     
35     //4.WeakRefs & FinalizationRegistry對象 ...
36     //5.Promise.any & AggregateError ...
37 }

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM