摘要:雖然正則中可以匹配任何字符,但卻無法匹配換行符。精讀文中列舉的四個新特性是加入到正則中的。討論地址是精讀正則如果你想參與討論,請點擊這里,每周都有新的主題,周末或周一發布。
1. 引言
本周精讀的文章是 regexp-features-regular-expressions。
這篇文章介紹了 ES2018 正則支持的幾個重要特性:
Lookbehind assertions - 后行斷言
Named capture groups - 命名捕獲組
s (dotAll) Flag - . 匹配任意字符
Unicode property escapes - Unicode 屬性轉義
2. 概述還在用下標匹配內容嗎?匹配任意字符只有 [wW] 嗎?現在正則有更簡化的寫法了,事實上正則正在變得更加易用,是時候更新對正則的認知了。
2.1. Lookbehind assertions完整的斷言定義分為:正/負向斷言 與 先/后行斷言 的笛卡爾積組合,在 ES2018 之前僅支持先行斷言,現在終于支持了后行斷言。
解釋一下這四種斷言:
正向先行斷言 (?=...) 表示之后的字符串能匹配 pattern。
const re = /Item(?= 10)/; console.log(re.exec("Item")); // → null console.log(re.exec("Item5")); // → null console.log(re.exec("Item 5")); // → null console.log(re.exec("Item 10")); // → ["Item", index: 0, input: "Item 10", groups: undefined]
負向先行斷言 (?!...) 表示之后的字符串不能匹配 pattern。
const re = /Red(?!head)/; console.log(re.exec("Redhead")); // → null console.log(re.exec("Redberry")); // → ["Red", index: 0, input: "Redberry", groups: undefined] console.log(re.exec("Redjay")); // → ["Red", index: 0, input: "Redjay", groups: undefined] console.log(re.exec("Red")); // → ["Red", index: 0, input: "Red", groups: undefined]
在 ES2018 后,又支持了兩種新的斷言方式:
正向后行斷言 (?<=...) 表示之前的字符串能匹配 pattern。
先行時字符串放前面,pattern 放后面;后行時字符串放后端,pattern 放前面。先行匹配以什么結尾,后行匹配以什么開頭。
const re = /(?<=€)d+(.d*)?/; console.log(re.exec("199")); // → null console.log(re.exec("$199")); // → null console.log(re.exec("€199")); // → ["199", undefined, index: 1, input: "€199", groups: undefined]
負向后行斷言 (? 表示之前的字符串不能匹配 pattern。
注:下面的例子表示 meters 之前 不能匹配 三個數字。
const re = /(?文中給了一個稍復雜的例子,結合了 正向后行斷言 與 負向后行斷言:
注:下面的例子表示 meters 之前 能匹配 兩個數字,且 之前 不能匹配 數字 35.const re = /(?<=d{2})(? 2.2. Named Capture Groups命名捕獲組可以給正則捕獲的內容命名,比起下標來說更可讀。
其語法是 ?
: const re = /(?d{4})-(? d{2})-(? d{2})/; const [match, year, month, day] = re.exec("2020-03-04"); console.log(match); // → 2020-03-04 console.log(year); // → 2020 console.log(month); // → 03 console.log(day); // → 04 也可以在正則表達式中,通過下標 1 直接使用之前的捕獲組,比如:
解釋一下,1 代表 (ww) 匹配的內容而非 (ww) 本身,所以當 (ww) 匹配了 "ab" 后,1 表示的就是對 "ab" 的匹配了。console.log(/(ww)1/.test("abab")); // → true // if the last two letters are not the same // as the first two, the match will fail console.log(/(ww)1/.test("abcd")); // → false對于命名捕獲組,可以通過 k
的語法訪問,而不需要通過 1 這種下標: 下標和命名可以同時使用。const re = /(?2.3. s (dotAll) Flagw+)s+k /; const match = re.exec("I"m not lazy, I"m on on energy saving mode"); console.log(match.index); // → 18 console.log(match[0]); // → on on 雖然正則中 . 可以匹配任何字符,但卻無法匹配換行符。因此聰明的開發者們用 [wW] 巧妙的解決了這個問題。
然而這終究是個設計缺陷,在 ES2018 支持了 /s 模式,這個模式下,. 等價于 [wW]:
console.log(/./s.test(" ")); // → true console.log(/./s.test(" ")); // → true2.4. Unicode Property Escapes正則支持了更強大的 Unicode 匹配方式。在 /u 模式下,可以用 p{Number} 匹配所有數字:
u 修飾符可以識別所有大于 0xFFFF 的 Unicode 字符。const regex = /^p{Number}+$/u; regex.test("231???"); // true regex.test("???"); // true regex.test("ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ"); // truep{Alphabetic} 可以匹配所有 Alphabetic 元素,包括漢字、字母等:
const str = "漢"; console.log(/p{Alphabetic}/u.test(str)); // → true // the w shorthand cannot match 漢 console.log(/w/u.test(str)); // → false終于有簡便的方式匹配漢字了。2.5. 兼容表可以到 原文 查看兼容表,總體上只有 Chrome 與 Safari 支持,Firefox 與 Edge 都不支持。所以大型項目使用要再等幾年。
3. 精讀文中列舉的四個新特性是 ES2018 加入到正則中的。但正如兼容表所示,這些特性基本還都不能用,所以不如我們再溫習一下 ES6 對正則的改進,找一找與 ES2018 正則變化的結合點。
3.1. RegExp 構造函數優化當 RegExp 構造函數第一個參數是正則表達式時,允許指定第二個參數 - 修飾符(ES5 會報錯):
new RegExp(/book(?=s)/giu, "iu");不痛不癢的優化,,畢竟大部分時間構造函數不會這么用。
3.2. 字符串的正則方法將字符串的 match()、replace()、search、split 方法內部調用時都指向到 RegExp 的實例方法上,比如
String.prototype.match 指向 RegExp.prototype[Symbol.match]。
也就是正則表達式原本應該由正則實例觸發,但現在卻支持字符串直接調用(方便)。但執行時其實指向了正則實例對象,讓邏輯更為統一。
舉個例子:
"abc".match(/abc/g) / // 內部執行時,等價于 abc / g[Symbol.match]("abc");3.3. u 修飾符概述中,Unicode Property Escapes 就是對 u 修飾符的增強,而 u 修飾符是在 ES6 中添加的。
u 修飾符的含義為 “Unicode 模式”,用來正確處理大于 uFFFF 的 Unicode 字符。
同時 u 修飾符還會改變以下正則表達式的行為:
點字符原本支持單字符,但在 u 模式下,可以匹配大于 0xFFFF 的 Unicode 字符。
將 u{61} 含義由匹配 61 個 u 改編為匹配 Unicode 編碼為 61 號的字母 a。
可以正確識別非單字符 Unicode 字符的量詞匹配。
S 可以正確識別 Unicode 字符。
u 模式下,[a-z] 還能識別 Unicode 編碼不同,但是字型很近的字母,比如 u212A 表示的另一個 K。
基本上,在 u 修飾符模式下,所有 Unicode 字符都可以被正確解讀,而在 ES2018,又新增了一些 u 模式的匹配集合來匹配一些常見的字符,比如 p{Number} 來匹配 ?。
3.4. y 修飾符y 修飾符是 “粘連”(sticky)修飾符。
y 類似 g 修飾符,都是全局匹配,也就是從上次成功匹配位置開始,繼續匹配。y 的區別是,必須是上一次匹配成功后的下一個位置就立即匹配才算成功。
比如:
/a+/g.exec("aaa_aa_a"); // ["aaa"]3.5. flags通過 flags 屬性拿到修飾符:
const regex = /[a-z]*/gu; regex.flags; // "gu"4. 總結本周精讀借著 regexp-features-regular-expressions 這篇文章,一起理解了 ES2018 添加的正則新特性,又順藤摸瓜的整理了 ES6 對正則做的增強。
如果你擅長這種擴散式學習方式,不妨再進一步溫習一下整個 ES6 引入的新特性,筆者強烈推薦阮一峰老師的 ECMAScript 6 入門 一書。
ES2018 引入的特性還太新,單在對 ES6 特性的使用應該和對 ES3 一樣熟練。
如果你身邊的小伙伴還對 ES6 特性感到驚訝,請把這篇文章分享給他,防止退化為 “只剩項目經驗的 JS 入門者”。
討論地址是:精讀《正則 ES2018》 · Issue #127 · dt-fe/weekly如果你想參與討論,請點擊這里,每周都有新的主題,周末或周一發布。前端精讀 - 幫你篩選靠譜的內容。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101787.html
摘要:舉例來說即便某個失敗了,也不會導致的發生,這樣在不在乎是否有項目失敗,只要拿到都結束的信號的場景很有用。對于則稍有不同只要有子項,就會完成,哪怕第一個了,而第二個了,也會,而對于,這種場景會直接。 1. 引言 本周精讀的內容是:Google I/O 19。 2019 年 Google I/O 介紹了一些激動人心的 JS 新特性,這些特性有些已經被主流瀏覽器實現,并支持 polyfill...
摘要:目前我們的業務項目采用的來進行優化和首屏性能提升??勺冃孕枰岄_發人員降低開發時的基準線,來保證每一個用戶的體驗。對于路由的切分以及庫的引入來說,這一個原則至關重要。快速生成一份站點的性能審查報告。 The Cost Of JavaScript 2018 關于原文 原文是在Medium上面看到的,Chrome工程師Addy Osmani發布的一篇文章,這位的Medium上面的自我介紹里...
摘要:解析可以分為如下四步詞法分析,將字符串拆分成包含關鍵詞識別的字符段。涉及到語意處理就要考慮上下文,而這都不是詞法分析階段要考慮的。更多討論討論地址是精讀手寫編譯器詞法分析如果你想參與討論,請點擊這里,每周都有新的主題,周末或周一發布。 1 引言 因為工作關系,需要開發支持眾多方言的 SQL 編輯器,所以復習了一下編譯原理相關知識。 相比編譯原理專家,我們只需要了解部分編譯原理即可實現 ...
摘要:引言是一個版語法解析器生成器,具有分詞語法樹解析的能力。實現函數用鏈表設計函數是最佳的選擇,我們要模擬調用棧了。但光標所在的位置是期望輸入點,這個輸入點也應該參與語法樹的生成,而錯誤提示不包含光標,所以我們要執行兩次。 1. 引言 syntax-parser 是一個 JS 版語法解析器生成器,具有分詞、語法樹解析的能力。 通過兩個例子介紹它的功能。 第一個例子是創建一個詞法解析器 my...
摘要:嵌套對象成員會造成重大性能影響盡量少用。一般來說你可以通過這種方法提高代碼的性能將經常使用的對象成員數組項和域外變量存入局部變量中。在反復訪問的地方使用局部變量存放引用小心地處理集合因為他們表現出存在性總是對底層文檔重新查詢。 前言 本期我來給大家推薦的書是《高性能JavaScript》,在這本書中我們能夠了解 javascript 開發過程中的性能瓶頸,如何提升各方面的性能,包括代碼...
閱讀 1208·2021-09-30 09:47
閱讀 3758·2021-09-06 15:02
閱讀 1765·2021-09-01 10:46
閱讀 2353·2019-08-30 15:52
閱讀 587·2019-08-29 15:28
閱讀 1867·2019-08-29 15:08
閱讀 1142·2019-08-29 13:28
閱讀 2565·2019-08-29 12:19