ES10 目前可以使用的5個新特性

譯者:前端小智

原文:blog.logrocket.com/5-es2019-fe…

爲了保證可讀性,本文采用意譯而非直譯。

ECMAScript 2015,也稱爲ES6,是一個花了6年時間完成的主要版本。從那時起,負責ECMAScript標準開發的技術委員會39 (TC39)每年都會發布該標準的新版本。這個年度發佈週期簡化了這個過程,並使新特性快速可用,JavaScript社區對此表示歡迎。

今年,ECMAScript 2019(簡稱ES2019)將會發布。 新功能包括Object.fromEntries()trimStart()trimEnd()flat()flatMap(),symbol對象的description屬性,可選的catch綁定等。

好消息是這些功能已經在最新版本的Firefox和Chrome中實現,並且它們也可以被轉換,以便舊版瀏覽器能夠處理它們。

1. Object.fromEntries()

在JavaScript中,將數據從一種格式轉換爲另一種格式非常常見。 爲了便於將對象轉換爲數組,ES2017引入了Object.entrie()方法。 此方法將對象作爲參數,並以[key,value]的形式返回對象自己的可枚舉字符串鍵控屬性對的數組。 例如:

const obj = {one: 1, two: 2, three: 3};

console.log(Object.entries(obj));    
// => [["one", 1], ["two", 2], ["three", 3]]
複製代碼

但是如果我們想要做相反的事情並將鍵值對列表轉換爲對象呢? 某些編程語言(如Python)爲此提供了dict()函數。 在Underscore.jsLodash中還有_.fromPairs函數。

ES2019引入Object.fromEntries()方法爲JavaScript帶來類似的功能, 此靜態方法允許你輕鬆地將鍵值對列表轉換爲對象:

const myArray = [['one', 1], ['two', 2], ['three', 3]];
const obj = Object.fromEntries(myArray);

console.log(obj);    // => {one: 1, two: 2, three: 3}
複製代碼

如你所見,Object.fromEntries()Object.entries()所做的事情正好相反。 雖然以前可以實現Object.fromEntries()相同的功能,但它實現方式有些複雜:

const myArray = [['one', 1], ['two', 2], ['three', 3]];
const obj = Array.from(myArray).reduce((acc, [key, val]) 
=> Object.assign(acc, {[key]: val}), {})
console.log(obj);    // => {one: 1, two: 2, three: 3}
複製代碼

請記住,傳遞給Object.fromEntries()的參數可以是實現可迭代協議的任何對象,只要它返回一個兩元素,類似於數組的對象即可。

例如,在以下代碼中,Object.fromEntries()Map對象作爲參數,並創建一個新對象,其鍵和對應值由Map中的對給出:

const map = new Map();
map.set('one', 1);
map.set('two', 2);

const obj = Object.fromEntries(map);

console.log(obj);    // => {one: 1, two: 2}
複製代碼

Object.fromEntries() 方法對於轉換對象也非常有用,思考以下代碼:

const obj = {a: 4, b: 9, c: 16};

// 將對象轉換爲數組
const arr = Object.entries(obj);

// 計算數字的平方根
const map = arr.map(([key, val]) => [key, Math.sqrt(val)]);

// 將數組轉換回對象
const obj2 = Object.fromEntries(map);

console.log(obj2);  // => {a: 2, b: 3, c: 4}
複製代碼

上述代碼將對象中的值轉換爲其平方根。 爲此,它首先將對象轉換爲數組,然後使用map()方法獲取數組中值的平方根,結果是可以轉換回對象的數組。

使用Object.fromEntries()的另一種情況是處理URL的查詢字符串,如本例所示

const paramsString = 'param1=foo&param2=baz';
const searchParams = new URLSearchParams(paramsString);

Object.fromEntries(searchParams);    // => {param1: "foo", param2: "baz"}
複製代碼

此代碼中,查詢字符串將傳遞給 URLSearchParams()構造函數。 然後將返回值(即URLSearchParams對象實例)傳遞給Object.fromEntries() 方法,結果是一個包含每個參數作爲屬性的對象。

Object.fromEntries() 方法目前是第4階段提案,這意味着它已準備好包含在ES2019標準中。

2. trimStart() and trimEnd()

trimStart()trimEnd()方法在實現與trimLeft()trimRight()相同。這些方法目前處於第4階段,將被添加到規範中,以便與padStart()padEnd()保持一致,來看一些例子:

const str = "   string   ";

// es2019
console.log(str.trimStart());    // => "string   "
console.log(str.trimEnd());      // => "   string"

// 相同結果
console.log(str.trimLeft());     // => "string   "
console.log(str.trimRight());    // => "   string"
複製代碼

對於Web兼容性,trimLeft()trimRight() 將保留爲trimStart()trimEnd() 的別名。

3. flat() and flatMap()

flat() 方法可以將多維數組展平成一維數組

const arr = ['a', 'b', ['c', 'd']];
const flattened = arr.flat();

console.log(flattened);    // => ["a", "b", "c", "d"]
複製代碼

以前,我們經常使用reduce()concat()來展平多維數組:

const arr = ['a', 'b', ['c', 'd']];
const flattend = [].concat.apply([], arr);

// or
// const flattened =  [].concat(...arr);

console.log(flattened);    // => ["a", "b", "c", "d"]
複製代碼

請注意,如果提供的數組中有空值,它們會被丟棄:

const arr = ['a', , , 'b', ['c', 'd']];
const flattened = arr.flat();

console.log(flattened);    // => ["a", "b", "c", "d"]
複製代碼

flat() 還接受一個可選參數,該參數指定嵌套數組應該被展平的級別數。 如果未提供參數,則將使用默認值1

const arr = [10, [20, [30]]];

console.log(arr.flat());     // => [10, 20, [30]]
console.log(arr.flat(1));    // => [10, 20, [30]]
console.log(arr.flat(2));    // => [10, 20, 30]
複製代碼

flatMap() 方法將map()flat()組合成一個方法。 它首先使用提供的函數的返回值創建一個新數組,然後連接該數組的所有子數組元素。 來個例子:

const arr = [4.25, 19.99, 25.5];

console.log(arr.map(value => [Math.round(value)]));    
// => [[4], [20], [26]]

console.log(arr.flatMap(value => [Math.round(value)]));    
// => [4, 20, 26]
複製代碼

數組將被展平的深度級別爲1.如果要從結果中刪除項目,只需返回一個空數組:

const arr = [[7.1], [8.1], [9.1], [10.1], [11.1]];

// do not include items bigger than 9
arr.flatMap(value => {
  if (value >= 10) {
    return [];
  } else {
    return Math.round(value);
  }
});  

// returns:
// => [7, 8, 9]
複製代碼

除了正在處理的當前元素外,回調函數還將接收元素的索引和對數組本身的引用。flat()flatMap()方法目前處於第4階段。

4.Symbol 對象的 description 屬性

在創建Symbol時,可以爲調試目的向其添加description (描述)。有時候,能夠直接訪問代碼中的description 是很有用的。

ES2019 中爲Symbol對象添加了只讀屬性 description ,該對象返回包含Symbol描述的字符串。

let sym = Symbol('foo');
console.log(sym.description);    // => foo

sym = Symbol();
console.log(sym.description);    // => undefined

// create a global symbol
sym = Symbol.for('bar');
console.log(sym.description);    // => bar
複製代碼

5.可選的 catch

try catch 語句中的catch有時候並沒有用,思考下面代碼:

try {
  // 使用瀏覽器可能尚未實現的功能
} catch (unused) {
  // 這裏回調函數中已經幫我們處理好的錯誤
}
複製代碼

此代碼中的catch回調的信息並沒有用處。 但這樣寫是爲了避免SyntaxError錯誤。 ES2019可以省略catch周圍的括號:

try {
  // ...
} catch {
  // ....
}
複製代碼

另外:ES2020 的 String.prototype.matchAll

matchAll() 方法是ES2020 第4階段提議,它針對正則表達式返回所有匹配(包括捕獲組)的迭代器對象。

爲了與match()方法保持一致,TC39 選擇了**“matchAll”**而不是其他建議的名稱,例如 “matches” 或 Ruby的 “scan”。看個簡單的例子:

const re = /(Dr\. )\w+/g;
const str = 'Dr. Smith and Dr. Anderson';
const matches = str.matchAll(re);

for (const match of matches) {
  console.log(match);
}

// logs:
// => ["Dr. Smith", "Dr. ", index: 0, input: "Dr. Smith and Dr. Anderson", groups: undefined]
// => ["Dr. Anderson", "Dr. ", index: 14, input: "Dr. Smith and Dr. Anderson", groups: undefined]
複製代碼

此正則表達式中的捕獲組匹配字符**“Dr”**,後跟一個點和一個空格。\w+ 匹配任何單詞字符一次或多次。 並且g標誌指示引擎在整個字符串中搜索模式。

之前,必須在循環中使用exec()方法來實現相同的結果,這不是非常有效:

const re = /(Dr\.) \w+/g;
const str = 'Dr. Smith and Dr. Anderson';
let matches;

while ((matches = re.exec(str)) !== null) {
  console.log(matches);
}

// logs:
// => ["Dr. Smith", "Dr.", index: 0, input: "Dr. Smith and Dr. Anderson", groups: undefined]
// => ["Dr. Anderson", "Dr.", index: 14, input: "Dr. Smith and Dr. Anderson", groups: undefined]
複製代碼

重要的是要注意儘管match() 方法可以與全局標誌g一起使用來訪問所有匹配,但它不提供匹配的捕獲組或索引位置。 比較以下代碼:

const re = /page (\d+)/g;
const str = 'page 2 and page 10';

console.log(str.match(re));    
// => ["page 2", "page 10"]

console.log(...str.matchAll(re)); 
// => ["page 2", "2", index: 0, input: "page 2 and page 10", groups: undefined] 
// => ["page 10", "10", index: 11, input: "page 2 and page 10", groups: undefined]
複製代碼

總結

在這篇文章中,我們仔細研究了 ES2019 中引入的幾個關鍵特性,包括Object.fromEntries()trimStart(), trimEnd(), flat(), flatMap()symbol 對象的description 屬性以及可選的catch

儘管一些瀏覽器還沒有完全實現這些特性,但可以使用Babel和其他JavaScript轉換器,仍然可以在項目中使用它們。


作者:前端小智
鏈接:https://juejin.im/post/5d1166b5f265da1b725c0f88
來源:掘金
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章