摘要:,和中新增功能的示例原文鏈接翻譯鏈接始終緊跟的最新功能是很難的,更難的是找到有用的代碼示例。和其他雙字節字符上的和和其它雙字節字符串使用的多字節表示。所以和可能無法按照預期的工作。提醒展開運算符用于等號的右側,解構運算符用于等號的左側。
ECMAScript 2016,2017和2018中新增功能的示例
原文鏈接: medium.freecodecamp.org
翻譯鏈接:https://www.zcfy.cc/article/h...
始終緊跟Javascript(ECMAScript)的最新功能是很難的,更難的是找到有用的代碼示例。
因此,在本文中,我將介紹在TC39的最終提案中包含的18個功能,這些功能將被添加到ES2016, ES2017, and ES2018 (最終草案)中,并通過有實際用處的示例來展示它們。
這是一篇非常長的貼子,但應該非常容易閱讀。把它當作“Netflix狂歡閱讀” 讀完之后,我保證你將掌握大量有關這些功能的知識。
讓我們一個一個地看看這些新功能
1. Array.prototype.includesincludes是Array實例上一個非常簡的方法,可以非常容易查找到某一項是否在Array中(包括 NaN 而不像 indexOf不能查找NaN)。
const arr = [1, 2, 3, 4, NaN]; // Instead of if (arr.indexOf(3) >= 0) { console.log(true); } // Use if (arr.includes(3)) { console.log(true); } arr.includes(NaN); // true arr.indexOf(NaN); // -1
花絮:JavaScript規范制定者想將它命名為contains,但是這個名字已經明確地被Mootools用了,所他們使用includes。2. 指數 運算符
數學運算如加法和減法分別有+和- 等中綴運算符。與他們類似,中綴運算符通常用于指數運算。在ECMAScript 2016中,引入了來代替Math.pow。
Math.pow(7,2) // 49 //Now 7**2 // 49
1、Object.values()
Object.values()是一個類似于Object.keys()的新函數,它返回對象自有屬性的所有值,而不包括原型鏈上的任何值。
const cars = { BMW: 2, TESLA: 2, TOYOTA: 1 }; // ES2015 const vals = Object.keys(cars).map(key => cars[key]); console.log(vals); // [3,2,1] // ES2017 const values = Object.values(cars); console.log(values);
2、 Object.entries()
Object.entries()與Object.keys有關,但不僅僅返回鍵,而是以數組的形式返回鍵和值。這使得在循環中使用對象,或將對象轉到Maps等變得非常簡單。
示例 1:
const cars = { BMW: 2, TESLA: 2, TOYOTA: 1 }; // ES5.1 Object.keys(cars).forEach(function(key) { console.log("key: " + key + "value" + carsp[key]); }); // ES8 for (let [key, value] of Object.entries(cars)) { console.log(`key: ${key} value:${value}`); }
示例 2:
const cars = { BMW: 2, TESLA: 2, TOYOTA: 1 }; // ES2015 const map1 = new Map(); Object.keys(cars).forEach(key => { map1.set(key, cars[key]); }); console.log(map1); // Map(3){"BMW" => 2, "TESLA" => 2, "TOYOTA" => 1} // ES8 const map = new Map(Object.entries(cars)); console.log(map); // Map(3){"BMW" => 2, "TESLA" => 2, "TOYOTA" => 1}3. 字符串填充
String新增了兩個實例謝謝老婆---String.prototype.padStart 和 String.prototype.padEnd?,它們允許在原始字符串的開始和結尾處添加空字符串或者是其它的字符串。
"someString".padStart(字符串的總長度 [,填充字符串]); "5".padStart(10) // " 5" "5".padStart(10, "=*") //"=*=*=*=*=5" "5".padEnd(10) // "5 " "5".padEnd(10, "=*") //"5=*=*=*=*="
當我們想要漂亮的打印顯示或終端打印等場景中對齊輸出時,將變得的很方便。
3.1 padStart 示例:
在下面的示例中,有一些不同長度的數字,我們想在它們前面填充“0”,以便所有的項目都將以10位的相同長度用于顯示。我們可以使用padStart(10, "0")很容易的實現。
// ECMAScript 2017 const formatted = [0, 1, 12, 123, 1234, 12345].map(num => num.toString().padStart(10, "0") ); console.log(formatted);// ["0000000000", "0000000001", "0000000012", "0000000123", "0000001234", "0000012345"]
3.2 padEnd 示例:
當我們想右對齊打印多個不同長度的項目時,使用padEnd就非常方便了。
下面是一個非常好實例,它展示了padEnd 、padStart 和 Object.entries如何結合使用產生一個漂亮的輸出。
const cars = { "?BMW": "10", "?Tesla": "5", "?Lamborghini": "0" } Object.entries(cars).map(([name, count]) => { //padEnd appends "-" until the name becomes 20 characters //padStart prepends "0" until the count becomes 3 characters. console.log(`${name.padEnd(20, "-")} Count: ${count.padStart(3, "0")}`) }); //Prints.. // ?BMW - - - - - - - Count: 010 // ?Tesla - - - - - - Count: 005 // ?Lamborghini - - - Count: 000
3.3 ?? Emojis和其他雙字節字符上的padStart和padEnd
Emojis和其它雙字節字符串使用unicode的多字節表示。所以padStart和padEnd可能無法按照預期的工作??。
例如:假設我們嘗試用 ??表示符號填充字符中heart到10個字符,結果如下所示:
//Notice that instead of 5 hearts, there are only 2 hearts and 1 heart that looks odd! "heart".padStart(10, "??"); // prints.. "?????heart"
這是因為 ??是2個碼長("u2764uFE0F")!單詞heart是5個字符,所以我僅剩下5個字符用于填充。所以最終JS使用"u2764uFE0F"填充了兩個心型????。最一個?的產生是因為JS僅使用了第一個字節u2764。
所以最后輸出: ?????heart
PS:你可通過這個鏈接查看unicode字符轉換。4. Object.getOwnPropertyDescriptors
這個方法返回一個對象的所有屬性的詳細信息(包括get和set方法)。添加這個方法的主要目的是允許淺拷貝/克隆一個對象,包括對象上的getter和setter函數,不同于Object.assign。
Object.assign 允許淺復制源對象上的所有屬性的詳細信息,除getter和setter函數外。
下面的示例通過拷貝一個原始對象Car到一個新對象ElectricCar,來展示Object.assign和Object.getOwnPropertyDescriptors以及Object.defineProperties之間的區別。你會發現使用Object.getOwnPropertyDescriptors,discount的getter和setter函數同樣被拷貝到目標對象。
var Car = { name: "BMW", price: 1000000, set discount(x) { this.d = x; }, get discount() { return this.d; }, }; //Print details of Car object"s "discount" property console.log(Object.getOwnPropertyDescriptor(Car, "discount")); //prints.. // { // get: [Function: get], // set: [Function: set], // enumerable: true, // configurable: true // } //Copy Car"s properties to ElectricCar using Object.assign const ElectricCar = Object.assign({}, Car); //Print details of ElectricCar object"s "discount" property console.log(Object.getOwnPropertyDescriptor(ElectricCar, "discount")); //prints.. // { // value: undefined, // writable: true, // enumerable: true, // configurable: true // } //??Notice that getters and setters are missing in ElectricCar object for "discount" property !?? //Copy Car"s properties to ElectricCar2 using Object.defineProperties //and extract Car"s properties using Object.getOwnPropertyDescriptors const ElectricCar2 = Object.defineProperties({}, Object.getOwnPropertyDescriptors(Car)); //Print details of ElectricCar2 object"s "discount" property console.log(Object.getOwnPropertyDescriptor(ElectricCar2, "discount")); //prints.. // { get: [Function: get], ?????? // set: [Function: set], ?????? // enumerable: true, // configurable: true // } // Notice that getters and setters are present in the ElectricCar2 object for "discount" property!5. 在函數參數中添加尾隨逗號
這是一個小的更新,它允許我們在函數最后一個參數的后面添加尾隨逗號。為什么這么做?它可以幫助像git blame這樣的工具確認所有的責任都是新的開發者引起的。
下面的示例說明這個問題和解決方法。
注意:你可以尾隨逗號來調用函數。6. Async/Await
如果你問我,我會說這個迄今為止最重要也是最有用的功能。異步函數允許們再也不用處理回調地獄,同時使用整個代碼看起來很簡單。
async關鍵字告訴JavaScript編譯器,以不同的方式處理這個函數。在函數內執行到await關鍵字時,編譯器將會暫停。它假設在等待之后的表達式返回一個承諾,并等待承諾解決或拒絕后繼續執行。
在這個示例中,getAmount函數將調用兩個異步的函數getUser 和 getBankBalance。我們可以通過Promise實現,但使用async await會更加的優雅和簡單。.
6.1 異步函數本身返回一個Promise.
如果你想等待一個異步函數的返回結果,你需要你需要使用Promise’s then語法來捕獲返回結果。
在下面的示例中,我們想通過console.log來打印返回結果,而不是在doubleAndAdd函數內部。所以我們想等函數返回結果并通過then語法將結果傳遞給console.log 。
6.2 并行調用async/await
在上一個示例中,我們調用了兩次await語句,每一次等待1s(共2s)。In the previous example we are calling await twice, but each time we are waiting for one second (total 2 seconds). 相反,我們可以使用Promise.all并行執行兩次調用,因為a和b。
6.3 async/await函數的錯誤處理
使用async await時,有各種方法來處理錯誤。
選項 1?—在函數中使用try catch
//Option 1 - Use try catch within the function async function doubleAndAdd(a, b) { try { a = await doubleAfter1Sec(a); b = await doubleAfter1Sec(b); } catch (e) { return NaN; //return something } return a + b; } //?Usage: doubleAndAdd("one", 2).then(console.log); // NaN doubleAndAdd(1, 2).then(console.log); // 6 function doubleAfter1Sec(param) { return new Promise((resolve, reject) => { setTimeout(function() { let val = param * 2; isNaN(val) ? reject(NaN) : resolve(val); }, 1000); }); }
Option 2— 捕獲每個一個 await 表達式
因為每一個await表達式都返回一個Promise,你可以像下面展示在每一行上捕獲錯誤。
//Option 2 - *Catch* errors on every await line //as each await expression is a Promise in itself async function doubleAndAdd(a, b) { a = await doubleAfter1Sec(a).catch(e => console.log(""a" is NaN")); // ? b = await doubleAfter1Sec(b).catch(e => console.log(""b" is NaN")); // ? if (!a || !b) { return NaN; } return a + b; } //?Usage: doubleAndAdd("one", 2).then(console.log); // NaN and logs: "a" is NaN doubleAndAdd(1, 2).then(console.log); // 6 function doubleAfter1Sec(param) { return new Promise((resolve, reject) => { setTimeout(function() { let val = param * 2; isNaN(val) ? reject(NaN) : resolve(val); }, 1000); }); }
Option 3?—?捕獲整個 async-await 函數
//Option 3 - Dont do anything but handle outside the function //since async / await returns a promise, we can catch the whole function"s error async function doubleAndAdd(a, b) { a = await doubleAfter1Sec(a); b = await doubleAfter1Sec(b); return a + b; } //?Usage: doubleAndAdd("one", 2) .then(console.log) .catch(console.log); // ???`<------- use "catch" function doubleAfter1Sec(param) { return new Promise((resolve, reject) =>` { setTimeout(function() { let val = param * 2; isNaN(val) ? reject(NaN) : resolve(val); }, 1000); }); }
ECMAScript目前正在最張草案中,將于2018年6月或7月發布。 is currently in final draft and will be out in June or July 2018. 下文函數的所有功能都將在Stage-4中,并將成為ECMAScript 2018的一部分。1. 共享內存和原子
這是一個偉大的、非常先進的功能,是對JS引擎的核心增強。
它的主要思想是想為JS提供一些多線程的功能,以便JS開發人員可以自己管理內存(代替JS引擎對內存的管理)來編寫高性能的并發程序。
這是通過一種叫做SharedArrayBuffer的全局對象來實現的,它實質上是將數據存儲在_共享_ 內存空間中。所以這個數據可以在JS主線程和web-worker之間共享。
到現在為止,如果我們想在JS主線程和web-workers之間共享數據,只能先復制數據然后使用postMessage 發送到其它線程。
現在,只需要使用SharedArrayBuffer,主線程和多個web工作線程即可訪問共享數據。
但是在線程之間共享內存會引發競爭條件的產生。為了防止條件的產生引入了“Atomics”全局對象。 當一個線程正在使用它的數據時,Atomics 提供了各種方法來鎖定共享內存。 它還提供了安全地更新共享內存中的數據的方法。
建議通過某些庫來使用這些功能,但是現在還沒有構建在此功能上的庫。
如果你有興趣,推薦閱讀:
From Workers to Shared Memor_y?—?_lucasfcosta
A cartoon intro to SharedArrayBuffers_?—?_Lin Clark
Shared memory and atomics_?—?_Dr. Axel Rauschmayer
首先,我們要弄清楚“Tagged Template literal”是什么,這樣我們才能更好的理解這個特性。
在ES2015+中,有一個叫標簽模板的功能,它允許開發人員自定義如何插入字符串。例如,以標簽方式插入字符串,如下所示... ...
在標簽中,可以寫一個函數來接收字符串常量部分,如[ ‘Hello ‘, ‘!’ ]和要替換的變量,如[ "Raja"], 把它們作為參數傳入自定義的函數(如greet),然后從這個自定義的函數中返回任何所需要的內容。
下面的示例展示了我們自定義的標簽函數greet給某個時間附加如“Good Morning!”、“Good afternoon”這些字符串,取決于某個具體的時間并返回一個自定義的字符串。
//A "Tag" function returns a custom string literal. //In this example, greet calls timeGreet() to append Good //Morning/Afternoon/Evening depending on the time of the day. function greet(hardCodedPartsArray, ...replacementPartsArray) { console.log(hardCodedPartsArray); //[ "Hello ", "!" ] console.log(replacementPartsArray); //[ "Raja" ] let str = ""; hardCodedPartsArray.forEach((string, i) => { if (i < replacementPartsArray.length) { str += `${string} ${replacementPartsArray[i] || ""}`; } else { str += `${string} ${timeGreet()}`; //<-- append Good morning/afternoon/evening here } }); return str; } //?Usage: const firstName = "Raja"; const greetings = greet`Hello ${firstName}!`; //??<-- Tagged literal console.log(greetings); //"Hello Raja! Good Morning!" ? function timeGreet() { const hr = new Date().getHours(); return hr < 12 ? "Good Morning!" : hr < 18 ? "Good Afternoon!" : "Good Evening!"; }
現在我們討論被當作標識名的函數到底是什么,許多人希望在不同的場景中使用這個功能,例如在終端命令和HTTP請求的URI構成中,等。
??The problem with Tagged String literal
問題是在ES2015和ES2016規范中不允許使用`“u” (unicode),“x”(hexadecimal) 等轉義字符,除非它們看起來完全像u00A9 或 u{2F804} 或 xA9。
因此,如果你在一個標記函數內使用其它域的規則(如終端規則),那么可能需要使用ubla123abla這種規則,它看起來不像u0049 或 u{@F804},然后你將會得到一個語法錯誤。
在ES2018中,使用規則是非常寬松的,甚至無效的轉義字符。只要標記函數通過對象返回屬性值,如“cooked”(無效字符串是“undefined”)和“raw”(包括任何其它你想要的屬性)。
function myTagFunc(str) { return { "cooked": "undefined", "raw": str.raw[0] } } var str = myTagFunc `hi
正則表達式的“dotall”標志
在現在的RegEx中,盡管(“.”)應該匹配單個字符,便它不匹配會產生新的字符,像n r f等。
例如:
//Before /first.second/.test("first second"); //false
這個增強的功能可以使點運算符匹配任何單符。為了確保不破壞任何內容,我們需要使用s標記來創建RegEx表示以使其能正常工作。
//ECMAScript 2018 /first.second/s.test("first second"); //true Notice: /s ??
以下是(提案)[https://github.com/tc39/propo...] 文檔中的全部API:
4. RegEx命名的組捕獲 ?這個增強的功能模仿其它語言,如Python,Java等中帶來一個非常有用的特性叫“命名組”。此特性允許開發人員編寫RegExp時,為RegExp中的組的不同部分提供格式為“(
4.1 基本的命名組示例
在下面的示例中,我們使用(?
4.2 在正則表達式本身內使用命名組
我們可以使用k <組名>這種格式在正則表達式本身反向引用該組。 下面的例子展示它的工作原理:
4.3 在String.prototype.replace中使用命名組
現在,命名組這個特性已經可以在字符串的實例方法replace中使用了,所以我們可以很容易地替換字符串的單詞。
例如,把“firstName, lastName”替換成“lastName, firstName”。
5. 對象的解構屬性解構操作符 ... (三個...)允許我們提取對象中沿未提取的屬性。
5.1 你可以使用解構來只提取你想要的屬性
5.2 更方便的是你可以刪除你不想要的屬 ??
6. 對象的屬性擴展擴展屬性也是使用三個點 ...,解構屬性,不同的是使用擴展創建(重新構建)的是新的對象。
提醒:展開運算符用于等號的右側,解構運算符用于等號的左側。
7. RegExp Lookbehind Assertions這是RegEx的一個增強的功能,它可以使我們確保某些字符串一定在其它的字符中之前。
您現在可以使用一個組(?<= ...) (問號,小于,等于)來查找肯定的斷言。
此外,您可以使用(?<!...)(問號,小于,感嘆號)來查看否定斷言。從本質上講,只要-ve斷言通過,就會匹配。
肯定的斷言: 比如說,我們希望確保#在單詞winning之前(即:#winning),并希望正則表達之返回字符串“winning”,下面展示它的寫法。
否定的斷言: 比方說,我們希望獲取€而不是$字符之后的數字。
8. RegExp Unicode 轉義要編寫RegEx來匹配各種Unicode字符是很難的。諸如 w, W, d等只能匹配英文字符和數字。 但是對于印度語,希臘語等其他語言的數字呢?
這就是Unicode Property Escapes的用武之地。結果是,Unicode為每個符號(字符)添加了元數據屬性,并使用它來對各種符號進行分組或表征。
例如,Unicode數據庫將所有印地語字符(??????)分組在一個key為Script、值為Devanagari的屬性下,另一個key為Script_Extensions的屬性值也為Devanagari。所以我們可以搜索Script = Devanagari并獲得所有的印地文字符。
` Devanagari 可用于馬拉地語,北印度語,梵語等各種印度語言。
從ECMAScript 2018開始,我們可以使用 p轉義字符和{Script = Devanagari}來匹配所有印度字符。 也就是說,我們可以在RegEx中使用: p {Script = Devanagari} 來匹配所有Devanagari字符。
//The following matches multiple hindi character
/^p{Script=Devanagari}+$/u.test("??????");
//true
//PS:there are 3 hindi characters h
同樣,Unicode數據庫將所有希臘字符組合為Script_Extensions(和Script)屬性,其值為Greek。 所以我們可以使用Script_Extensions = Greek或Script = Greek來搜索所有希臘字符。
也就是說,我們可以在RegEx中使用: p {Script = Greek} 以匹配所有Greek字符。
//The following matches a single Greek character
/p{Script_Extensions=Greek}/u.test("π"); // true
此外,Unicode數據庫將各種類型的表情符號存儲在屬性值為“真”的布爾屬性Emoji,Emoji_Component,Emoji_Presentation,Emoji_Modifier和Emoji_Modifier_Base下。所以我們可以通過簡單的選擇“Emoji”來搜索所有的表情符號。
也就是說,我們可以使用: p {Emoji} , Emoji_Modifier 等來匹配各種表情符號。
下面的例子將會說明的更清晰一點。
//The following matches an Emoji character /p{Emoji}/u.test("??"); //true //The following fails because yellow emojis don"t need/have Emoji_Modifier! /p{Emoji}p{Emoji_Modifier}/u.test("??"); //false //The following matches an emoji characterp{Emoji} followed by p{Emoji_Modifier} /p{Emoji}p{Emoji_Modifier}/u.test("??"); //true //Explaination: //By default the victory emoji is yellow color. //If we use a brown, black or other variations of the same emoji, they are considered //as variations of the original Emoji and are represented using two unicode characters. //One for the original emoji, followed by another unicode character for the color. // //So in the below example, although we only see a single brown victory emoji, //it actually uses two unicode characters, one for the emoji and another // for the brown color. // //In Unicode database, these colors have Emoji_Modifier property. //So we need to use both p{Emoji} and p{Emoji_Modifier} to properly and //completely match the brown emoji. /p{Emoji}p{Emoji_Modifier}/u.test("??"); //true
最后,我們可以使用大寫的“P”( P )轉義字符而不是小p( p)來否定匹配。
參考:
ECMAScript 2018 Proposal
https://mathiasbynens.be/note...
Promise.prototype.finally()
finally() 是Promise新添加的實例方法。主要想法是允許在“resolve”或“reject”之后運行回調來處理其它邏輯。 finally **回調被調用時沒有任何價值,并且無論如何總是被執行。
看看不同的情況。
9. 異步迭代這是一個非常有用的功能。 基本上它允許我們輕松創建異步代碼循環!
這個特性增加了一個新的“for-await-of”循環,允許我們調用異步函數來返回承諾(或帶有一系列承諾的數組)。比較的酷的事情是,在下一個循環執行之前當前循環都會等待所有Promise返回承諾。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94648.html
摘要:在中,引入了代替。我們希望在為追加符讓所有項長度都為位,以便顯示,我們可以使用,輕松實現這一點。 showImg(https://segmentfault.com/img/bVbdReM?w=1000&h=401); 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 跟蹤JavaScript (ECMAScript)中的新內容是很困難的,而且更難找到有用的代碼示例。...
摘要:在中,引入了代替。我們希望在為追加符讓所有項長度都為位,以便顯示,我們可以使用,輕松實現這一點。 showImg(https://segmentfault.com/img/bVbdReM?w=1000&h=401); 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 跟蹤JavaScript (ECMAScript)中的新內容是很困難的,而且更難找到有用的代碼示例。...
摘要:詳情發布于月號發布了版本,除了性能改進修復外,首次添加了貢獻者的安裝腳本。詳情中的應用在中悄悄增加了對漸進式應用這一系列新技術的基本支持,這意味著現在可以在沒有批準的情況下在上安裝應用程序,不過會有一些限制。 01. ES2016, 2017, 2018 中的新特性 文章介紹了 18 個 ECMAScript 2016,2017 和 2018 中新增加的特性,這些特性已被加入到 TC3...
摘要:詳情發布于月號發布了版本,除了性能改進修復外,首次添加了貢獻者的安裝腳本。詳情中的應用在中悄悄增加了對漸進式應用這一系列新技術的基本支持,這意味著現在可以在沒有批準的情況下在上安裝應用程序,不過會有一些限制。 01. ES2016, 2017, 2018 中的新特性 文章介紹了 18 個 ECMAScript 2016,2017 和 2018 中新增加的特性,這些特性已被加入到 TC3...
摘要:詳情發布于月號發布了版本,除了性能改進修復外,首次添加了貢獻者的安裝腳本。詳情中的應用在中悄悄增加了對漸進式應用這一系列新技術的基本支持,這意味著現在可以在沒有批準的情況下在上安裝應用程序,不過會有一些限制。 01. ES2016, 2017, 2018 中的新特性 文章介紹了 18 個 ECMAScript 2016,2017 和 2018 中新增加的特性,這些特性已被加入到 TC3...
閱讀 3427·2021-11-12 10:36
閱讀 2734·2021-11-11 16:55
閱讀 2958·2021-09-27 13:36
閱讀 1615·2021-08-05 10:01
閱讀 3556·2019-08-30 15:55
閱讀 765·2019-08-30 13:01
閱讀 1906·2019-08-29 17:16
閱讀 2376·2019-08-29 16:40