2019谷歌I/O大會上提出的JavaScript新特性,你錯過了嗎?

2019谷歌I/O大會上提出的JavaScript新特性,你錯過了嗎?

2019谷歌I/O大會上提出的JavaScript新特性,你錯過了嗎?

圖片
做者 | Uday Hiwarale
譯者 | 王強
編輯 | Yonie
本文總結了 2019 年穀歌 I/O 大會上 Mathias 和 Sathya 提出來的 JavaScript 新規範功能。javascript

正則表達式 lookbehind

正則表達式(RegEx 或 正則表達式)在任何語言裏都是強大的功能。在字符串中搜索複雜的模式時正則表達式就能大顯身手了。以前 JavaScript 中的正則表達式實現已經很是齊全了,惟一缺乏的就是 lookbehind。html

Lookahead

首先咱們來了解一下正則表達式中的 lookahead 是什麼含義,JavaScript 已經支持 lookahead 了。正則表達式中的 lookahead 語法容許你在字符串中選出的模式具備如下屬性:另外一個已知模式正好緊靠這個模式或不與其相鄰,或者在這個模式 以後。例如在字符串「MangoJuice,VanillaShake,GrapeJuice」中,咱們可使用正向 lookahead 語法來查找旁邊有 Juice 的單詞,即 Mango 和 Grape。
有兩種類型的 lookahead,分別是正向 lookahead 和負向或否認的 lookahead。
正向 lookahead
正向 lookahead 選出的模式具備如下屬性:另外一個已知模式位於選出模式以後。正向 lookahead 的語法以下。前端

/[a-zA-Z]+(?=Juice)/

上面的模式選出了大寫或小寫字母的單詞,單詞旁邊都會有 Juice。不要把它和正則表達式中的捕獲組混淆。Lookahead 和 Lookbehind 都是寫在括號裏的,但它們沒有被捕獲。下面看一個正向 lookahead 的實際例子。java

const testString = "MangoJuice, VanillaShake, GrapeJuice";
const testRegExp = /[a-zA-Z]+(?=Juice)/g;
const matches = testString.match( testRegExp
 );
console.log( matches ); // ["Mango", "Grape"]

負向 lookahead

相似地,上面的例子中若是使用 負向 lookahead,就是選出全部後面沒有 Juice 的單詞。負向 lookahead 的語法與正向 lookahead 的語法相似,但有一處不一樣。咱們須要把 = 符號換成! 符號。
/[a-zA-Z]+(?!Juice)/
上面的正向表達式模式會選出全部後面不跟着 Juice 的單詞。但上面的模式會選出給定字符串中的全部單詞,由於給定字符串中的全部單詞都 不以 Juice 結尾,所以咱們須要更具體些的規則。web

/(Mango|Vanilla|Grape)(?!Juice)/

這種模式將選出 Mango、Vanilla 或 Grape 幾個單詞,它們後面沒有跟着 Juice。來看具體的代碼。正則表達式

const testString = "MangoJuice, VanillaShake, GrapeJuice";
const testRegExp= /(Mango|Vanilla|Grape)(?!Juice)/g;
const matches = testString.match( testRegExp
 );
console.log( matches ); // ["Vanilla"]

Lookbehind

與 lookahead 相似,Lookbehind 也是正則表達式中的一種語法,用它選出的模式具備如下屬性:字符串中的某個已知模式位於或不在它的 前面。例如,在字符串「FrozenBananas,DriedApples,FrozenFish」中,咱們可使用正向 lookbehind 來找到前面有 Frozen 的單詞,比好比 Bananas 和 Fish。
與 lookahead 相似,這裏也有一個正向 lookbehind 和負向或否認 lookbehind。
正向 lookbehind
正向 lookbehind 選出的模式具備如下屬性:另外一個已知模式位於它的前面。正向 lookbehind 的語法以下。算法

/(?<=Frozen)[a-zA-Z]+/

lookbehind 的模式相似於 lookahead,但帶有額外的<符號,表示在前。上面的模式會選出全部以 Frozen 開頭的單詞或者在前面有 Frozen 的單詞。來看具體的操做。編程

const testString = "FrozenBananas, DriedApples, FrozenFish";
const testRegExp = /(?<=Frozen)[a-zA-Z]+/g;
const matches = testString.match( testRegExp
 );
console.log( matches ); // ["Bananas", "Fish"]

負向 lookbehind

負向 lookbehind 選出的模式具備如下屬性:另外一個已知模式不在它的前面。例如要選出「FrozenBananas,DriedApples,FrozenFish」字符串中前面沒有 Frozen 的單詞,咱們將使用如下語法。數組

/(?<!Frozen)[a-zA-Z]+/

但上面的模式將選出字符串中的全部單詞,由於全部單詞前面都沒有 Frozen(FrozenBannanas 這樣的單詞這裏會被視爲一整個單詞),咱們須要更具體一些。promise

/(?<!Frozen)(Bananas|Apples|Fish)/

寫在代碼中:

const testString = "FrozenBananas, DriedApples, FrozenFish";
const testRegExp = /(?<!Frozen)(Bananas|Apples|Fish)/g;
const matches = testString.match( testRegExp
 );
console.log( matches ); // ["Apples"]

支持範圍——TC39:階段 4;Chrome:62+;Node:8.10.0+

類字段

類字段(class field) 是一種新的語法,用來從類構造函數外部定義實例(對象)的屬性。有兩種類型的類字段,公共類字段 和 私有類字段。
公共類字段
以前咱們必須在類構造函數中定義對象上的屬性。這些屬性是公共的,意味着能夠在類(對象)的實例上訪問它們。

class Dog {
    constructor() {
        this.name = 'Tommy';
    }
}

每當咱們有一個擴展父類的類時,必須先從構造函數中調用 super,而後才能在子類上添加屬性,以下所述。

class Animal {}
class Dog extends Animal {
    constructor() {
        super(); // call super before using `this` in constructor
        this.sound = 'Woof! Woof!';
    }
    makeSound() {
        console.log( this.sound );
    }
}
// create instance
const tommy = new Dog();
tommy.makeSound(); // Woof! Woof!

如今有了公共類字段語法,咱們就能夠在類的構造函數以外定義類字段,JavaScript 將隱式調用 super。

class Animal {}
class Dog extends Animal {
    sound = 'Woof! Woof!'; // public class field
    makeSound() {
        console.log( this.sound );
    }
}
// create instance
const tommy = new Dog();
tommy.makeSound(); // Woof! Woof!

當 JavaScript 隱式調用 super 時,它會在實例化類時傳遞用戶提供的全部參數(這是標準的 JavaScript 行爲,與私有類字段無關)。所以,若是你的父構造函數須要定製參數,請確保手動調用 super。

class Animal {
    constructor( ...args ) {
        console.log( 'Animal args:', args );
    }
}
class Dog extends Animal {
    sound = 'Woof! Woof!'; // public class field
makeSound() {
        console.log( this.sound );
    }
}
// create instance
const tommy = new Dog( 'Tommy', 'Loves', 'Toys!' );
tommy.makeSound(); // Animal args: [ 'Tommy', 'Loves', 'Toys!' ]

支持範圍——TC39:階段 3;Chrome:72+;Node:12+

私有類字段

衆所周知,JavaScript 沒有 public、private 和 protected 之類的屬性修飾符。默認狀況下,對象上的全部屬性都是公共的,這意味着任何人均可以訪問它們。想要定義一個對外界隱藏的屬性,最接近的方法是使用 Symbol 這個屬性名稱。你可能會使用 _ 前綴來表示應該是私有的屬性,但它只是一種表示法,不能解決問題。
如今有了私有類字段,咱們可讓類屬性只能在類中訪問,並防止它們反映在實例(對象)上。來看前面的一個例子,先看一個暴露的屬性。

class Dog {
    _sound = 'Woof! Woof!'; // this is private

    makeSound() {
        console.log( this._sound );
    }
}
// create instance
const tommy = new Dog();
console.log( tommy._sound ); // Woof! Woof!

添加 _ 前綴並不能解決咱們的問題。私有類字段的定義方式與定義公共類字段的方式相同,但咱們沒必要添加下劃線前綴,而是添加 # 前綴。訪問對象上的私有屬性將致使 SyntaxError: Undefined private field。

class Dog {
    #sound = 'Woof! Woof!'; // this is private
    makeSound() {
        console.log( this.#sound );
    }
}
// create instance
const tommy = new Dog();
tommy.makeSound() // Woof! Woof!
//console.log( tommy.#sound ); // SyntaxError

私有屬性只能在定義它們的類中訪問。所以在父類或子類內沒法訪問私有屬性。
咱們還可使用未定義的值定義私有(和公共)屬性。

class Dog {
    #name;
    constructor( name ) {
        this.#name = name;
    }
    showName() {
        console.log( this.#name );
    }
}
// create instance
const tommy = new Dog( 'Tommy' );
tommy.showName(); // Tommy

支持範圍——TC39:階段 3;Chrome:74+;Node:12+

string.matchAll

咱們在 string 數據類型上有 match 原型方法,它根據給定的正則表達式或關鍵字返回字符串中的匹配模式。

const colors = "#EEE, #CCC, #FAFAFA, #F00, #000";
const matchColorRegExp = /([A-Z0-9]+)/g;
console.log( colors.match( matchColorRegExp ) );
// Output:
["EEE", "CCC", "FAFAFA", "F00", "000"]

但這種方法不提供其餘附加信息,例如字符串中每一個匹配的索引。刪除 g 標誌後能夠生成其餘信息,但以後咱們只能得到第一個匹配項。

const colors = "#EEE, #CCC, #FAFAFA, #F00, #000";
const matchColorRegExp = /#([A-Z0-9]+)/;
console.log( colors.match( matchColorRegExp ) );
// Output: (result shortned for viewing purpose)
["#EEE", "EEE", index: 0, input: "<colors>"]

最後,咱們須要在正則表達式對象和語法上使用.exec 方法,這樣寫起來沒那麼複雜。咱們須要使用 while 循環,直到 exec 返回 null 爲止。但要注意,exec 不會返回迭代器。

const colors = "#EEE, #CCC, #FAFAFA, #F00, #000";
const matchColorRegExp = /#([A-Z0-9]+)/g;
// in strict mode,
// Uncaught ReferenceError: match is not defined
while( match = matchColorRegExp.exec( colors ) ) {
  console.log( match );
}
// Output: (result shortned for viewing purpose)
["#EEE", "EEE", index: 0, input: "<colors>"]
["#CCC", "CCC", index: 6, input: "<colors>"]
["#FAFAFA", "FAFAFA", index: 12, input: "<colors>"]
["#F00", "F00", index: 21, input: input: "<colors>"]
["#000", "000", index: 27, input: input: "<colors>"]

爲了解決這個問題,咱們如今有了 matchAll 方法,它返回一個迭代器,而且這個迭代器的每次 next() 調用都會連續返回匹配的項。

const colors = "#EEE, #CCC, #FAFAFA, #F00, #000";
const matchColorRegExp = /#([A-Z0-9]+)/g;
console.log( ...colors.matchAll( matchColorRegExp ) );
// Output: (result shortned for viewing purpose)
["#EEE", "EEE", index: 0, input: "<colors>"]
["#CCC", "CCC", index: 6, input: "<colors>"]
["#FAFAFA", "FAFAFA", index: 12, input: "<colors>"]
["#F00", "F00", index: 21, input: input: "<colors>"]
["#000", "000", index: 27, input: input: "<colors>"]

支持範圍——TC39:階段 4;Chrome:73+;Firefox:67+;Node:12+

命名捕獲組

與其餘語言相比,JavaScript 中捕獲或捕獲組的概念略有不一樣。每當咱們在括號內放置一個正則表達式模式(lookahead 和 lookbehind 除外)時,它就會變成一個捕獲組,全部匹配的模式都會反映在匹配的輸出項中。
在前面的示例中,下面數組的第一項是正則表達式模式的完整匹配,而第二項是捕獲組的匹配值。

["#EEE", "EEE", index: 0, input: "<colors>"]

若是有多個捕獲組,它們將連續顯示在結果中。咱們來看一個例子。

const str = "My name is John Doe.";
const matchRegExp = /My name is ([a-z]+) ([a-z]+)/i;
const result = str.match( matchRegExp );console.log( result );
// error, if result is null
console.log( { firstName: result[1], lastName: result[2] } );
// Output:
["My name is John Doe", "John", "Doe", index: 0, input: "My name is John Doe.", groups: undefined]
{firstName: "John", lastName: "Doe"}

如上所示,輸出的第一個元素是完整匹配的字符串,而第二個和第三個元素是捕獲組的結果。
如今有了命名捕獲組後,咱們可使用標籤將單個捕獲組結果保存在
groups 對象中。定義命名捕獲組的語法是 (?$pattern)。

const str = "My name is John Doe.";
const matchRegExp = /My name is (?<firstName>[a-z]+) (?<lastName>[a-z]+)/i;
const result = str.match( matchRegExp );
console.log( result );
console.log( result.groups );
// Output:
["My name is John Doe", "John", "Doe", index: 0, input: "My name is John Doe.", groups: {firstName: "John", lastName: "Doe"}]
{firstName: "John", lastName: "Doe"}

命名捕獲組也適用於 matchAll 方法。
支持範圍——TC39:階段 4;Chrome:64+;Node:10+

數字分隔符

咱們寫較大的整數或小數時,可讀性一直是個大問題。例如,十億寫成數字是 1000000000,但你得數對零的個數才行,不少時候這都很讓人頭疼。
在較新版本的 JavaScript 中,咱們可使用 _ 分隔符來分隔數字的各個部分,以加強可讀性

var billion = 1_000_000_000;
console.log( billion ); // 1000000000

咱們能夠隨意將 _ 放在數字中,而 JavaScript 只會忽略它。這種方法適用於任何類型的數字,不管是整數、十進制、二進制、十六進制仍是八進制數字都行。

console.log( 1_000_000_000.11 ); // 1000000000.11
console.log( 1_000_000_000.1_012 ); // 1000000000.1012
console.log( 0xFF_00_FF ); // 16711935
console.log( 0b1001_0011 ); // 147
console.log( 0o11_17 ); // 591

支持範圍——TC39:階段 3;Chrome:75+;Node:12.5+

BigInt

JavaScript 中的數字是從 Number 函數(也是構造函數)建立的。一個數字能夠可靠表示的最大值是(2⁵³ - 1),也就是 9007199254740991。也可使用 Number.MAX_SAFE_INTEGER 生成這個數。
當咱們寫下數字時,JavaScript 用 Number 構造函數包裝它,以生成一個在其原型上包含數字方法的對象。全部原始數據類型都會這樣處理。參閱 Primitives vs Objects 這篇 文章 來理解這個理念。
那麼若是咱們繼續加大這個數字會怎麼樣?

console.log( Number.MAX_SAFE_INTEGER ); // 9007199254740991
console.log( Number.MAX_SAFE_INTEGER + 10 ); // 9007199254741000

上面代碼中的最後一個日誌輸出返回了錯誤的結果。發生這種狀況是由於 JavaScript 沒法計算超過 Number.MAX_SAFE_INTEGER 值的數字。
如今有了 BigInt 就能解決這個問題了。BigInt 能讓咱們表示一個比 Number.MAX_SAFE_INTEGER 值更高的整數。與 Number 相似,BigInt 同時表現爲一個函數和一個構造函數。加入 BigInt 後,JavaScript 有了新的 bigint 內置原始數據類型來表示大整數。

var large = BigInt( 9007199254740991 );
console.log( large ); // 9007199254740991n
console.log( typeof large ); // bigint

JavaScript 會在整數的末尾添加 n 下標以表示 BigInt 整數形式。所以咱們只需在整數的最末尾附加 n 就能寫成 BigInt 了。
如今咱們有了 BigInt,就能夠安全地對具備 bigint 數據類型的大數字執行數學運算了。

var large = 9007199254740991n;
console.log( large + 10n ); // 9007199254741001n

使用 number 數據類型的數字與使用 bigint 數據類型的數字不一樣,由於 bigint 只能表示整數。所以程序不容許 bigint 和 number 數據類型之間的算術運算。
BigInt 函數能夠接受任何類型的數字,如整數、二進制、十六進制、八進制等。它會在內部統一轉換爲十進制。
BigInt 還支持數字分隔符。

var large = 9_007_199_254_741_001n;
console.log( large ); // 9007199254741001n

支持範圍——TC39:階段 3;Chrome:67+;Firefox:68+;Node:10.4+

數組:flat 和 flatMap

數組對象上的 flat 和 flatMap 原型方法。
Array.flat
咱們如今能在一個數組使用一個新的 flat(n) 原型方法,它將數組展平到第 n 個深度並返回一個新數組。默認狀況下 n 爲 1。咱們能夠將 n 做爲 Infinity 傳遞,以展平全部嵌套數組。

var nums = [1, [2, [3, [4, 5]]]];
console.log( nums.flat() ); // [1, 2, [3, [4,5]]]
console.log( nums.flat(2) ); // [1, 2, 3, [4,5]]
console.log( nums.flat(Infinity) ); // [1, 2, 3, 4, 5]

支持範圍——TC39:階段 4;Chrome:69+;Firefox:62+;Node:12+
Array.flatMap
平常編程工做中有時可能會使用 map 變換數組,而後將其展平。例如計算一些整數的平方。

var nums = [1, 2, 3];
var squares = nums.map( n => [ n, n*n ] )
console.log( squares ); // [[1,1],[2,4],[3,9]]
console.log( squares.flat() ); // [1, 1, 2, 4, 3, 9]

咱們可使用 flatMap 原型方法,用一個語法同時執行映射和展平。它只能將從回調函數返回的數組展平到 1 的深度。

var nums = [1, 2, 3];
var makeSquare = n => [ n, n*n ];
console.log( nums.flatMap( makeSquare ) ); // [1, 1, 2, 4, 3, 9]

支持範圍——TC39:階段 4;Chrome:69+;Firefox:62+;Node:11+

對象:fromEntries

咱們可使用 對象 的 entries 靜態方法提取對象的 key:value 對,該方法返回一個數組,其中每一個元素都是一個數組,後者的第一項是 key,第二項是 value。

var obj = {x:1,y:2,z:3};
var objEntries = Object.entries(obj);
console.log(objEntries); // [[「x」,1],[「y」,2],[「z」,3]]

咱們如今能夠在對象上使用 fromEntries 靜態方法,它會將條目轉換回對象。

var entries = [["x", 1],["y", 2],["z", 3]];
var obj = Object.fromEntries( entries );
console.log( obj ); // {x: 1, y: 2, z: 3}

以前咱們使用 entries 就能很容易地過濾和映射對象值,但將條目放回到對象表單卻很麻煩。這裏就可使用 fromEntries 簡化工做了。

var obj = { x: 1, y: 2, z: 3 };
// [["x", 1],["y", 2],["z", 3]]
var objEntries = Object.entries( obj );
// [["x", 1],["z", 3]]
var filtered = objEntries.filter(
 ( [key, value] ) => value % 2 !== 0 // select odd
);
console.log( Object.fromEntries( filtered ) ); // {x: 1, z: 3}

當咱們使用 Map 按插入順序存儲鍵值對時,內部數據結構與條目格式相似。咱們可使用 fromEntries 輕鬆地從 Map 構造一個對象。

var m = new Map([[「x」,1],[「y」,2],[「z」,3]]);
console.log(m); // {「x」=> 1,「y」=> 2,「z」=> 3}
console.log(Object.fromEntries(m)); // {x:1,y:2,z:3}

支持範圍——TC39:階段 4;Chrome:73+;Firefox:63+;Node:12+

globalThis

以前咱們很熟悉 JavaScript 中的 this 關鍵字。它沒有肯定的值,其值取決於訪問它的上下文。在任何環境中,當從程序的最頂層上下文訪問時 this 指向全局對象,這就是所謂的全局 this。
例如,在 JavaScript 中全局 this 是 window 對象,你能夠在 JavaScript 文件的頂部(最外層上下文)或 JavaScript 控制檯內添加 console.log(this) 語句來驗證這一點。2019谷歌I/O大會上提出的JavaScript新特性,你錯過了嗎?
圖片
this 全局值在 Node.js 內部會指向 global 對象,而在 web worker 內部會指向 web worker 自己。可是要獲取全局 this 值不太容易,由於咱們不能在全部位置使用 this 關鍵字;例如,在類構造函數中 this 值指向類實例。
所以其餘環境爲咱們提供了像 self 這樣的關鍵字,與 JavaScript 和 web worker 中的全局 this 同樣;而在 Node.js 中使用的是 global。使用這些替代關鍵字時,咱們能夠建立一個通用函數來返回全局 this 值。

const getGlobalThis = () => {
 if (typeof self !== 'undefined') return self;
 if (typeof window !== 'undefined') return window;
 if (typeof global !== 'undefined') return global;
 if (typeof this !== 'undefined') return this;
 throw new Error('Unable to locate global `this`');
};
var globalThis = getGlobalThis();

可是用這個 polyfill 獲取全局 this 對象會出問題,這篇文章解釋了緣由: https://mathiasbynens.be/notes/globalthis。爲了解決這個問題,JavaScript 如今提供了 globalThis 關鍵字,它能夠從任何地方返回全局 this 對象。

var obj = { fn: function() {
  console.log( 'this', this === obj ); // true
  console.log( 'globalThis', globalThis === window ); // true
} };
obj.fn();

支持範圍——TC39:階段 3;Chrome:71+;Firefox:65+;Node:12+

穩定排序

咱們對數組排序時,ECMAScript 不會爲 JavaScript 引擎提出排序算法,而只會強制執行排序 API 的語法。所以排序性能和 / 或排序穩定性會隨着瀏覽器或 JavaScript 引擎的不一樣而變化。
但如今 ECMAScript 強制數組排序算法保持穩定。這個答案介紹了排序穩定性更新: https://stackoverflow.com/a/1517824
簡而言之,若是排序結果(變異數組)中那些不受排序影響的項目順序不變,與一開始插入的順序一致,則排序算法就是穩定的。咱們來看一個例子吧。

var list = [
  { name: 'Anna', age: 21 },
  { name: 'Barbra', age: 25 },
  { name: 'Zoe', age: 18 },
  { name: 'Natasha', age: 25 }
];
// possible result
[
  { name: 'Natasha', age: 25 }
  { name: 'Barbra', age: 25 },
  { name: 'Anna', age: 21 },
  { name: 'Zoe', age: 18 },
]

如上所示,在 list 數組中,名爲 Barbra 的對象位於名爲 Natasha 的對象以前。因爲這些對象有着相同的年齡,咱們但願排序結果中它們保持相同的順序,但有時結果並不是如此。排序算法的結果會取決於你使用的 JavaScript 引擎。
可是如今,全部現代瀏覽器和 Node.js 默認使用 sort 方法進行穩定排序。這將始終產生如下結果。

// stable sort result
[
  { name: 'Barbra', age: 25 },
  { name: 'Natasha', age: 25 }
  { name: 'Anna', age: 21 },
  { name: 'Zoe', age: 18 },
]

一些 JavaScript 引擎之前支持穩定排序,但僅適用於較小的數組。爲了提升大型數組的性能,他們可能會使用更快的算法並犧牲排序穩定性。
支持範圍——Chrome:70+;Firefox:62+;Node:12+

國際化 API

國際化 API 是由 JavaScript 中的 ECMAScript 標準提供的 API,用於格式化指定語言中的數字、字符串、日期和時間。此 API 在 Intl 對象上可用。此對象提供構造函數,以便爲指定的區域設置建立與區域相關數據的格式化程序。可在 此處查看支持的區域設置列表: http://www.lingoes.net/en/translator/langcode.html
Intl.RelativeTimeFormat
在許多應用程序中,咱們一般須要以相對格式顯示時間,例如 5 分鐘前、昨天、1 周前 等。當咱們的網站須要區分不一樣區域的顯示內容時,咱們須要在分發包中存放全部可能的相對時間輸出組合 。
JavaScript 如今在 Intl 對象上提供了 RelativeTimeFormat9(locale, config) 構造函數,它容許你爲特定的區域設置建立時間格式化程序。這將建立一個具備 format(value, unit) 原型方法的對象來生成時間格式。

// español (spanish)
var rtfEspanol= new Intl.RelativeTimeFormat('es', {
  numeric: 'auto'
});
log( rtfEspanol.format( 5, 'day' ) ); // dentro de 5 días
log( rtfEspanol.format( -5, 'day' ) ); // hace 5 días
log( rtfEspanol.format( 15, 'minute' ) ); // dentro de 15 minutos

支持範圍——TC39:階段 3;Chrome:71+;Firefox:65+;Node:12+
Intl.ListFormat
ListFormat API 容許咱們將列表中的項目基於 and 或 or 格式組合在一塊兒。例如,[apples,mangoes,bananas] 使用並列格式就是 apples,mangoes and bananas,使用分離格式就是 apples,mangoes or bananas。
首先,咱們須要根據區域環境從 ListFormat(locale, config) 構造函數建立格式化程序實例,並使用 format(list) 原型方法生成特定於區域環境的列表格式。

// español (spanish)
var lfEspanol = new Intl.ListFormat('es', {
  type: 'disjunction'
});
var list = [ 'manzanas', 'mangos', 'plátanos' ];
log( lfEspanol.format( list ) ); // manzanas, mangos o plátanos

支持範圍——TC39:階段 3;Chrome:72+;Node:12+

Intl.Locale

除了語種名稱外,區域設置一般還有不少內容,如日曆類型、小時制、語言等。Intl.Locale(localeId, config) 構造函數用來基於提供的配置生成格式化的語言環境字符串。它建立的對象包含全部區域設置屬性,並暴露 toString 原型方法以獲取格式化的區域設置字符串。

const krLocale = new Intl.Locale( 'ko', {
  script: 'Kore', region: 'KR',
  hourCycle: 'h12', calendar: 'gregory'
} );
log( krLocale.baseName ); // ko-Kore-KR
log( krLocale.toString() ); // ko-Kore-KR-u-ca-gregory-hc-h12

在此處瞭解區域設置標識符和 Unicode 區域設置標記:https://unicode.org/reports/tr35/#unicode_locale_id
支持範圍——TC39:階段 3;Chrome:74+;Node:12+

Promise

以前,咱們在 Promise 構造函數上有 all 和 race 兩種靜態方法。Promise.all([... promises]) 返回一個 promise,它在輸入的全部promises 解析後才解析,輸入的任何promise 被拒絕時它也會被拒絕。Promise.race([... promises]) 返回一個 promise,輸入的任何 promise 解析後它就會解析,輸入的任何 promise 被拒絕後它也會被拒絕。
咱們迫切須要一個靜態方法來返回一個 promise,它要在全部 promise 完成後(解析或拒絕)解析。咱們還須要一個相似 race 的方法來返回一個 promise,等輸入的任何 promise 解析後它就會解析。
Promise.allSettled
Promise.allSettled 方法獲取一組 promise,並在全部 promise 都被解析或拒絕後解析。所以,此方法返回的 promise 不須要 catch 回調,由於它老是會解析。then 回調按照各個 promise 的順序接收每一個 promise 的 status 和 value。

var p1 = () => new Promise(
  (resolve, reject) => setTimeout( () => resolve( 'val1' ), 2000 )
);

var p2 = () => new Promise(
  (resolve, reject) => setTimeout( () => resolve( 'val2' ), 2000 )
);

var p3 = () => new Promise(
  (resolve, reject) => setTimeout( () => reject( 'err3' ), 2000 )
);
var p = Promise.allSettled( [p1(), p2(), p3()] ).then(
  ( values ) => console.log( values )
);
// Output
[ {status: "fulfilled", value: "val1"}
  {status: "fulfilled", value: "val2"}
  {status: "rejected", value: "err3"}
]

支持範圍——TC39:階段 3;Chrome:76+

Promise.any

Promise.any 方法相似於 Promise.race,可是隻要任何 promise 被拒絕,後者返回的 promise 就不會執行 catch 塊。相比之下,前者等任何 promise 解析後它返回的 promise 也會解析。若是沒有解析任何 promise,catch 塊將被執行。若是有任何 promise 先解析了,就會執行 then 塊。
支持範圍——TC39:階段 1
觀看本文視頻: https://www.youtube.com/watch?v=c0oy0vQKEZE
英文原文: https://itnext.io/whats-new-in-javascript-google-i-o-2019-summary-d16bd230841活動推薦前端人必備的《瀏覽器工做原理與實踐》上線了!7 大模塊,覆蓋性能優化、頁面渲染、JS、瀏覽器安全等內容,帶你全方位搞懂瀏覽器原理。掃碼看做者李兵,也算是瀏覽器領域的大牛了,08 年他就基於 Chromium 和 IE 發佈了一款雙核瀏覽器:太陽花,是國內第一款雙核瀏覽器。

相關文章
相關標籤/搜索