過去 4 年,最佳和最實用的 ES 特性!




自從 JavaScript 被發(fā)明以來,JavaScript 成為了世界上使用最多的編程語言之一。
每年,ECMA 都會發(fā)布一個帶來新特性的 JavaScript 版本。在這篇文章,我將會介紹在過去 4 年里引入的最佳和最實用的特性。
ES2018
展開操作符
ES2015 中最有趣的特性就是展開操作符(Spread Operator)。展開操作符使得復(fù)制和合并數(shù)組變得更簡單。與調(diào)用 concat() 或 slice() 不同,你可以使用 ... 操作符:
const array1 = [10, 20, 30];
const array2 = [40, 50];
// 合并數(shù)組 array2、array1
const merge = [...array1, ...array2];
console.log(merge);
// 輸出結(jié)果: [10, 20, 30, 40, 50]
ES2018 引入了相同的概念,但針對的是對象:
const object = {
a: 1,
b: 2,
c: 3
};
const { a, ...x } = object;
console.log(a)
console.log(x)
// 輸出結(jié)果:
// a = 1
// x = { b: 2, c: 3 }
并且,展開操作符也可以在其他對象中使用,例如:
const object1 = { a: 1, b: 2, c: 3 };
const object2 = { ...object1, z: 26 };
console.log(object2)
// 輸出結(jié)果:
// { a: 1, b: 2, c: 3, z: 26 }
Promise.prototype.finally()
ES2018 的另一個令人激動的特性就是 finally() 方法。
社區(qū)中有些 JavaScript 的庫(Library)也實現(xiàn)過類似的方法,這在很多場景下非常有用。
使用 finally() 方法,可以執(zhí)行一段代碼,而不必關(guān)注 Promise 的狀態(tài)是什么。讓我們來看一個簡單的例子:
fetch('file.json')
.then(data => data.json())
.catch(error => console.error(error))
.finally(() => console.log("finished"))
// 輸出結(jié)果: "finished"(和 fetch 的結(jié)果無關(guān))
ES2019
flat()
flat() 方法可以讓你輕松地拍平數(shù)組的所有子數(shù)組元素。例如,下面這個例子:
const arr = ['a', 'b', ['c', 'd']];
const flattened = arr.flat();
console.log(flattened);
// 輸出結(jié)果: ["a", "b", "c", "d"]
顯然,在這之前你只能使用 reduce() 或 concat() 來獲取到拍平后的數(shù)組:
const arr = ['a', 'b', ['c', 'd']];
const flattened = [].concat.apply([], arr);
// 或者
// const flattened = [].concat(...arr);
console.log(flattened);
// 輸出結(jié)果: ["a", "b", "c", "d"]
Object.fromEntries()
將數(shù)據(jù)從一種格式轉(zhuǎn)化成另一種格式,這是我們在使用 JavaScript 的過程中很常見的情景。為了便于將對象 Object 轉(zhuǎn)為數(shù)組 Array,ES2017 引入了 Object.entries() 方法。該方法將對象作為參數(shù),并且以 [key, value] 的方式返回對象本身可枚舉(Enumerable)的字符串鍵值 Key 和屬性值 Property。
但是,如果我們想做相反的事情,將鍵值對列表轉(zhuǎn)為對象呢?
ES2019 引入了新的特性 Object.fromEntries() 方法,通過使用這個方法你就可以做到:
const myArray = [['one', 1], ['two', 2], ['three', 3]];
const obj = Object.fromEntries(myArray);
console.log(obj);
// 輸出結(jié)果: {one: 1, two: 2, three: 3}
ES2020
可選鏈操作符
可選鏈操作符(Optional Chaining)將使你的代碼可讀性變得更好!
可選鏈操作符讓你可以每次訪問嵌套的對象屬性,而不需要驗證父屬性是否存在。
下面,我們通過例子來比較一下:
// 沒有使用可選鏈操作符
let userAdmin = undefined;
if (payload.access && payload.access.admin && payload.access.admin[0]) {
userAdmin = payload.access.admin[0].user;
}
// 使用可選鏈操作符
const userAdmin = payload.access?.admin?[0]?.user;
可以看到,我們可以不用 let 聲明一個變量并包含一些條件來給它賦值,而是直接用 const 聲明在一行并不需要任何條件判斷。
如果沒有找到對象上的屬性,將會返回 undefined。這真的非常實用!
空值合并操作符
空值合并操作符(Nullish Coalescing)增加了可以真正地檢查空值(Nullish)的能力,而不是檢查它是否為 false。那么,我想你可能會問空值和 false 的區(qū)別是什么?
在 JavaScript 中,許多值轉(zhuǎn)化為 Boolean 類型都會是 false,像空的字符串、數(shù)字 0、undefined、null、flase、NaN 等等。
在空值合并操作符出現(xiàn)之前,很多時候你可能想檢查一個變量是否為空值,它可能會是 undefined、null、空字符串,甚至是一個 false。
那么,現(xiàn)在這種情況下,你就可以使用空值合并操作符 ?? 來輕松處理!并且,我想這個時候,可能有同學(xué)會說 || 不是有同樣的效果嗎?下面,我們來通過例子看一下 || 和 ?? 不同的地方:
console.log(0 ?? true) // 0
console.log(0 || true) // true
console.log('' ?? 'Hello World!') // ''
console.log('' || 'Hello World!') // 'Hello World!'
console.log(false ?? true) // false
console.log(false || true) // true
console.log(NaN ?? 5) // Nan
console.log(NaN || 5) // 5
console.log(null ?? true) // true
console.log(null || true) // true
ES2021
String.prototye.replaceAll
String.prototype.replaceAll() 方法可以實現(xiàn)使用另一個字符串的值替換目標(biāo)字符串中滿足 pattern 部分的所有字符串。
在 JavaScript 中,.replace() 方法只會替換目標(biāo)字符串中滿足 pattern 部分的第一個字符串:
let string = "Wow, he doesn't like Porsche? I guess he must be crazy!"
string.replace("he","she")
// 輸出結(jié)果: "Wow, she doesn't like Porsche? I guess he must be crazy!"
如果我們想替換滿足 pattern 部分的所有字符串,實現(xiàn)這個的唯一方式是通過使用正則表達(dá)式的全局匹配。雖說使用正則表達(dá)式并不是一個壞的方法,但是從性能的角度分析,它并不是最好的。
而使用 .replaceAll() 方法,我們可以一次性更新滿足 pattern 的所有字符串,而不需要創(chuàng)建正則表達(dá)式:
let string = "Wow, he doesn't like Porsche? I guess he must be crazy!"
string.replaceAll("he","she")
// 輸出結(jié)果: "Wow, she doesn't like Porsche? I guess she must be crazy!"
數(shù)字分割符
現(xiàn)在,數(shù)字分隔符(Numeric Separators)主要是一個表面性的改變,對實際代碼的性能影響很小,但它可能有助于避免在需要向代碼中插入數(shù)值時出現(xiàn)錯誤。
數(shù)字分隔符將會加快讀取數(shù)字的速度,盡管這只是一個非常小的提升。即使,數(shù)字分隔符的引入不是一個巨大的更新,并不會改變我們的程序。但是,不可否認(rèn)的是數(shù)字分隔符是一個非常棒的特性:
const MILLION = 1_000_000; // 1000000
const BILLION = 1_000_000_000; // 1000000000
并且,數(shù)字分隔符最酷的地方在于,它還可以用在數(shù)字的小數(shù)點之后!下面,我們來看一下對應(yīng)的使用:
const BIGNUMBER = 1234_5678_9_0; // 1234567890
const PI = 3.1415_9265_3589; // 3.141592653589
另外需要注意的是,以下劃線開頭或結(jié)尾的整數(shù)和數(shù)字將拋出異常 ReferenceError 和 SyntaxError:
const BAD_PI = 3.14_15_; // SyntaxError
const NO_MILLION = _1_000_000; // ReferenceError點贊??、在看??
通過閱讀本篇文章,如果有收獲的話,可以點個贊和在看,這將會成為我持續(xù)分享的動力,感謝~





