ES 7 新特性
Array.prototype.includes
JavaScript
// Array.prototype.includes
const arr = [1];
// 與 indexOf 一樣
if (arr.indexOf(1) !== -1)
console.log(`A: 存在 1`);
if (arr.includes(1))
console.log(`B: 存在 1`);
// 也可以替代多個判斷
let test = 'a';
if (test === 'a' || test === 'b' || test == 'c')
console.log(`A: 存在a或b或c`);
if (['a', 'b', 'c'].includes(test))
console.log(`B: 存在a或b或c`);
指數運算符 **
JavaScript
// 相等於 Math.pow
console.log("A", Math.pow(2, 10));
console.log("B", 2 ** 10);
ES 8 新特性
字符串填充 String.padStart 及 String.padEnd
JavaScript
/**
* 字符串填充目的是令字串添加字符達到指定長度
* padStart 是在字串前面添加,padEnd 是在字串後面添加
*/
// String.padStart(targetLength, [padString])
console.log("A", '0.0'.padStart(4, '10'));
console.log("B", '0.0'.padStart(20));
console.log("C", '0.0'.padStart(15, 'cdef'));
// String.padEnd(targetLength, [padString])
console.log("D", '0.0'.padEnd(4, '0'));
console.log("E", '0.0'.padEnd(20));
console.log("F", '0.0'.padEnd(15, "cdef"));
Object.values()
JavaScript
/**
* Object.values()
* 返回一個包含所有對象自身屬性值的數組
*/
const person = { name: 'Peter', age: 20};
console.log(Object.values(person));
const people = ['Peter', 'David'];
console.log(Object.values(people));
Object.entries()
JavaScript
/**
* Object.entries()
* 返回一個包含所有對象自身屬性的數組,作為 [key,value]
*/
const person2 = { name: 'David', age: 30};
console.log(Object.entries(person2));
const people2 = ['David', 'Peter'];
console.log(Object.entries(people2));
for(let [key,value] of Object.entries(person2)){
console.log(`${key}: ${value}`);
}
async / await
JavaScript
/**
* async / await
* 利用async函數將異步操作包起來
* 在函數內部使用await 命令等待異步操作完成
**/
const readFile = function(fileName){
return new Promise(function (resolve, reject){
// read file logic
if(error) return reject(error);
resolve(data);
});
}
const asyncReadFile = async function(){
const file1 = await readFile('filePath1');
const file2 = await readFile('filePath2');
console.log(file1.toString());
console.log(file2.toString());
}
ES 9 新特性
Promise.finally()
JavaScript
/**
* Promise.finally()
* 無論Promise 成功或失敗,也是運行裡面的代碼
*/
// IOS真機環境下Promise 對象不存在finally方法
if(!Promise.prototype.finally){
Promise.prototype.finally = function(cb){
return this.then((res) => {
cb && cb(res);
}, (error) => {
cb && cb(error);
});
};
}
Object Rest / Spread
JavaScript
/**
* Object Rest / Spread
* 三個點 (...) 用於 Array
* Rest 參數可以允許將不一定數量的參數提取為1個Array
*/
send(1,2,3,4,5,6);
function send(p1, p2, ...p3){
// p1 = 1
// p2 = 2
// p3 = [3, 4, 5, 6]
}
// ...p3 即提取剩餘參數,並以Array來儲存
const values = [99, 100, -1, 48, 16];
console.log(Math.max(...values)); // 100
// 可以給函數傳送參數
send({
a: 1,
b: 2,
c: 3
});
function send({a, ...x}){
// a = 1
// x = { b: 2, c: 3 }
}
// 可以用作Object 複製
const obj1 = { a: 1, b: 2, c: 3};
const obj2 = { ...obj1, z: 26};
// obj2 會是 { a: 1, b: 2, c: 3, z: 26}
正則表達式命名
JavaScript
/**
* 正則表達式命名
* 可以使用符號 "?",在"?"後立即命名
*/
// 原正則寫法: /([0-9]{4})-([0-9]{2})-([0-9]{2})/
// 利用正則表達式命名
const newDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;
const match = newDate.exec('2020-04-30');
const year = match.groups.year; // 2020
const month = match.groups.month; // 04
const day = match.groups.day; // 30
// 也可以使用在 replace()中,將日期轉換成其他格式
const testDate = '2018-04-30';
const updatedDate = testDate.replace(newDate, '$<month>-$<day>-$<year>'); // 04-30-2018
異步迭代
JavaScript
/**
* 異步迭代
* 可以利用此特性輕鬆創建異步代碼循環
*
*/
const fn = (time) => {
return new Promise((resolve, reject){
setTimeout(() => {
resolve(`${time}s 後,執行成功了`);
}, time);
});
};
let arr = [fn(3000), fn(2000), fn(1000)];
async function fn2(){
for await(e of arr){
console.log(e);
}
}
fn2();
// 輸出如下
// 3000s 後,執行成功了
// 2000s 後,執行成功了
// 1000s 後,執行成功了
ES 10 新特性
String.trimStart() 及 String.trimEnd()
JavaScript
/**
* String.trimStart() 及 trim.End()
* 清除字串首或尾空白字符
*/
console.log(" aaa".trimStart()); // aaa
console.log("bbb ".trimEnd()); // bbb
Object.fromEntries()
JavaScript
/**
* Object.fromEntries()
* 返回一個給定對象自身可枚舉屬性的鍵值Array
* Object.fromEntries() 是 Object.entries() 的反轉
* Object.fromEntries() 可以將 map或Array 轉成 Object
*/
const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c']] ;
const obj = Object.fromEntries(arr); // { 0: "a", 1: "b", 2: "c" }
Array.flat() 及 Array.flatMap()
JavaScript
/**
* Array.flat() 及 Array.flatMap()
* flat() 用於 Array 降維,還可以去除Array 的 null
* flatMap() 相當於 map()的基礎上將結果壓平1層
*/
// flat() 降維
const arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2); // 壓平2層
// [1, 2, 3, 4, 5, 6]
// flat() 去除 null
const arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]
// flatMap() 壓平1層
const arr1 = [1, 2, 3, 4];
arr1.map(x => [x * 2]); // [[2], [4], [6], [8]]
arr1.flatMap(x => [x * 2]); //[2, 4, 6, 8]
// flatMap() 只能壓平一層
arr1.flatMap(x => [[x * 2]]); // [[2], [4], [6], [8]]
修改 catch 綁定
JavaScript
/**
* 修改 catch 綁定
*/
// 以前的寫法
try{} catch(e) {}
// 現在的寫法
try{} catch{}
ES 11 新特性
Optional Chaining
JavaScript
/**
* Optional Chaining
* 用作判斷屬性是否存在,更簡潔的寫法
*/
// 過往的寫法
const street = user.info && user.info.address && user.info.address.street;
// 現在的寫法
const street = user.info?.address?.street;
Nullish coalescing Operator
JavaScript
/**
* Nullish coalescing Operator
* 空值合併運算符
* 當左側為 null 或 undefined 時,返回右側的參數,否則返回左側的參數
* 與 || 的分別是, || 是左側為false 的情況也會當作是
*/
const undefinedValue = response.settings.undefinedValue ?? 'some other default';
String.prototype.matchAll
JavaScript
/**
* String.prototype.matchAll
* matchAll() 返回一個包含所有匹配正則表達式及分組捕獲結果的迭代器,包括子項
*/
const regexp = /t(e)(st(\d?))/g;
const str = 'test1test2';
str.match(regexp); // match方法
// Array ['test1', 'test2']
let array = [...str.matchAll(regexp)]; // matchAll 返回的是一個迭代器,不能直接守為Array
array[0]; // ['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', length: 4]
array[1]; // ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', length: 4]
Promise.allSettled
JavaScript
/**
* Promise.allSettled
* allSettled 統一處理 Promise的狀態
* 當所有Promise 對象狀態都變為resolved 或 rejected時,返回一個狀態Array
*/
const promise1 = new Promise(function(resolve, reject){
setTimeout(function(){
reject("promise1");
}, 2000);
});
const promise2 = new Promise(function(resolve, reject){
setTimeout(function(){
resolve("promise2");
}, 3000);
});
const promise3 = Promise.resolve("promise3");
const promise4 = Promise.reject("promise4");
Promise.allSettled([promise1, promise2, promise3, promise4]).then((args) => {
console.log(args);
/*
輸出如下
result:
[
{"status": "rejected", "reason": "promise1"},
{"status": "fulfilled", "reason": "promise2"},
{"status": "fulfilled", "reason": "promise3"},
{"status": "rejected", "reason": "promise4"},
]
*/
});
Class的private function 及 variable
JavaScript
/**
* Class 的private function 及 variable
* 使用 # 可以在Class 中定義
*/
class Foo{
#a;
#b;
constructor(a, b){
this.#a = a;
this.#b = b;
}
#sum(){
return this.#a + this.#b;
}
printSum(){
console.log(this.#sum());
}
}
ES 12 新特性
String.replaceAll
JavaScript
/**
* String.replaceAll
* 替換所有匹配字符串
*/
const str = "Hello world, Hello Peter!";
const new_str = str.replaceAll("Hello", "Hi");
console.log(new_str); // Hi world, Hi Peter!
Logical Assignment Operators 邏輯賦值操作符
JavaScript
/**
* Logical Assignment Operators 邏輯賦值操作符
* 旨在不影響可讀性的情況下盡可能最小化代碼量
*/
a ||= b; // 等同於 a || ( a = b);
a &&= b; // 等同於 a && (a = b);
a ??= b; // 等同於 a ?? (a = b);
// 可用於緩存變量,減少耗時操作,提高性能,例如
return this.appShowScene ??= wx.getStorageSync('appShowScene');
// 等同於以下
if(this.appShowScene){
return this.appShowScene;
}
this.appShowScene = wx.getStorageSync('appShowScene');
return this.appShowScene;
Promise.any()
JavaScript
/**
* Promise.any
* Promise.any() 有一個子實例成功就會當作成功
* 當全部都失敗才會失敗
*/
Promise.any([promise1, promise2]).then(() => {})
// promise1 和 promise2 任意一個成功就會 then
Numeric separators 數字分隔符
JavaScript
/**
* Numeric separators 數字分隔符
* 數字分隔符不影響原本的數值,增加可讀性
*/
console.log(1_000_000_000); // 1000000000
console.log(10.000_001); // 10.000001