深入理解ES6 002【學習筆記】

字串與正規表達式

字串與正規表達式

Javascript 字串一直基於 16 位元字元編碼(UTF-16)進行建構。每 16 位元的序列是一個編碼單元(code unit),代表一個字元。length、charAt() 等字串屬性與方法都基於這個編碼單元構造的。
Unicode 的目標是為世界上每一個字元提供全球唯一的識別符。如果我們把字元長度限制在 16 位元,碼位數量將不足以表示如此多的字元。「全球唯一的識別符」,又稱作碼位(code point),是從 0 開始的數值。而表示字元的這些數值或碼位,我們稱之為字元編碼 (character encode)。字元編碼必須將碼位編碼為內部一致的編碼單元。對於 UTF-16 來說,碼位可以由多種編碼單元表示。

更好的 Unicode 支援,在過去 16 位元足以包含任何字元 (每 16 位元的序列是一個編碼單元,代表一個字元,在過去 16 位元足以包含任何字元),直到Unicode引入擴展字元集,編碼規則才不得不進行變更。

UTF-16

前 $2^{16}$ 個碼位均以 16 位元的編碼單元表示,這個範圍被稱作基本多文種平面 BMP (Basic Multilingual Plan)。超出這個範圍的碼位則要歸屬於某個輔助平面(supplementary plane),UTF-16 引入了代理對,其規定用兩個 16 位元編碼單元表示一個碼位。這也就是說,字串裡的字元有兩種,一種是由一個編碼單元16表示的 BMP 字元,另一種是由兩個編碼單元32位元表示的輔助平面字元,如字元:‘𠮷’ (String.fromCodePoint(134071))

ECMAScript 5中,所有字串的操作都基於 16 位元編碼單元。如果採用同樣的方式處理包含代理對的UTF-16編碼字元,得到的結果可能與預期不符

let text = "𠮷";
console.log(text.length); //2
console.log(/^.$/.test(text)); //false
console.log(text.charAt(0)); // "" 
console.log(text.charAt(1)); // ""
console.log(text.charCodeAt(0)); // 55362
console.log(text.charCodeAt(1)); // 57271
  • 變數 text 的長度事實上是 1,但它的 length 屬性卻是 2
  • 變數 text 被判定為兩個字元,因此匹配單一字元的正規表達式失效
  • 前後兩個 16 位元的編碼單元都不表示任何可列印的字元,因此charAt()方法不會返回合法字串
  • charCodeAt() 同樣不能正確地辨識字元。它會返回每個 16 位元編碼單元對應的數值

codePointAt()方法

對於 BMP 字元集中的字元,codePointAt()方法的返回值與chartCodeAt()方法相同,而對於非 BMP 字元集來說返回值則不同。字串‘𠮷a’第一個字元是非 BMP 的,包含兩個編碼單元,所以它的 length 屬性值為 3。ES6 完全支援UTF-16codePointAt()方法,這個方法接受編碼單元的位置而非字元位置作為參數,返回與字串中給定位置對應的碼位,即一個整數值。

let text = '𠮷a'
console.log(text.length)

console.log(text.charCodeAt(0)) // 55362
console.log(text.charCodeAt(1)) // 57271
console.log(text.charCodeAt(2)) // 97

console.log(text.codePointAt(0)) // 134071
console.log(text.codePointAt(1)) // 57271
console.log(text.codePointAt(2)) // 97

在偵測一個字元佔用的編碼單元,可以寫如下的函式來偵測

function is32Bite(c){
  return c.codePointAt(0)>0xFFFF;
}

console.log(is32Bite('𠮷')) // true
console.log(is32Bite('a')) // false

fromCodePoint()方法

透過一個字元的碼位返回一個字元,可以看成是String.fromCharCode()的擴展版。對於 BMP 的所有字元,兩個方法的執行結果相同。只有傳遞非 BMP 的碼位作為參數時,二者的執行結果才有可能不同。

console.log(String.fromCodePoint(134071)) // 𠮷

normalize()方法

Unicode 的另一個有趣之處是,如果我們要對不同字元進行排序或比較操作,會存在一種可能,它們是等效的。代表相同文字的字元可能存在的碼位不同。所以做比較時要使用normalize()方法來先標準化一下

只要牢記,在對比字串之前,一定先把它們標籤化為同一個形式。

let normalized  = values.map(funciton(text){
  return text.normalize();
});

normalized.sort(funciton(first,second){
  if(first < second){
    return -1;
  } else if (first === second) {
    return 0;
  } else {
    return 1;
  }
})

正規表達式 u 修飾符

一個支援Unicode的修飾符u 使它從編碼單元操作模式切換成為字元模式,如此一來正規表達式就不會將代理對視為兩個字元,從而完全按照預期正常執行。如:

let text = '𠮷a'

console.log(text.length)
console.log(/^.$/.test(text)) //false
console.log(/^.$/u.test(text)) //true 使用了u修飾符後,正規表達式會匹配字元,從而就可以匹配日文文字字元

計算碼位數量

ES6 仍然不支援字串碼位數量偵測(length 仍然返回字串編碼單元的數量),但有了u修飾符後,你就可以透過正規表達式來解決這個問題。

// 長字串可能會有效率問題,可以使用字串迭代器來處理
function codePointLength(text){
  let rs = text.match(/[\s\S]/gu);
  return rs?rs.length:0
}
// 判斷瀏覽器是否支援 u
function hasRegExU(){
  try{
    var partten = new RegExp(".","u");
     return true
  }catch(ex){
    return false
  }
}

字串的子字串辨識

  • trim()
  • includes() 如果字串的起始部分偵測到指定文字則返回 true,否則返回 false
  • startWith()如果字元的起始部分偵測到指定文字則返回 true,否則返回 false
  • endsWith() 如果字串的結束部分偵測到指定文字則返回 true,否則返回 false
  • repeat() 返回當前字串重複一定次數的新字串

兩個參數,第一個指定要搜尋的文字,第二個參數是可選的,指定搜尋位置的索引位置,如果你需要在一個字串中尋找一個子字串的實際位置,還是需要使用indexOf()lastIndexOf()方法

repeat()方法

ES6 還增加了一個repeat(),它接受一個 number 型別的參數,表示該字串的重複次數,返回值是當前字串重複一定次數後的新字串。例如在程式碼格式化工具中建立縮排層級

let indent = " ".repeat(4),
indentLevel = 0;
// 當需要增加縮排時
let newIndent = indent.repeat(++indentLevel)

正規表達式中的 y 修飾符

它會影響正規表達式搜尋過程中的 sticky 屬性,當在字串中開始字元匹配時,它會通知搜尋從正規表達式的 lastIndex 屬性開始進行。如果在指定位置沒有成功匹配,則停止繼續匹配。只有呼叫 exec() 和 test() 這些正規表達式物件的方法時才會涉及 lastIndex 屬性

正規表達式的複製

var reg1 = /ab/i,
// ES5 中拋出例外,ES6 中正常執行
reg2 = new RegExp(reg1,"g")

let re = /ab/g
console.log(re.source); // "ab"
console.log(re.flags); // "g"

樣板字面值

  • 多行字串:一個正式的多行字串概念
  • 基本的字串格式化:將變數的值嵌入字串的能力
  • HTML 跳脫:向 HTML 插入經過安全置換後的字串的能力

樣板字面值裡不需要跳脫單引號、雙引號,如果要使用反引號則需要透過 \ 來

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4309

(0)
Walker的頭像Walker
上一篇 2025年3月8日 10:59
下一篇 2025年3月8日 02:11

相關推薦

  • Go工程師體系課 001【學習筆記】

    轉型 想在短時間系統轉到Go工程的理由 提高CRUD,無自研框架經驗 提升技術深度,做專、做精需求的同學 進階工程化,擁有良好開發規範和管理能力的 工程化的重要性 高階開發的期望 良好的程式碼規範 深入底層原理 熟悉架構 熟悉k8s的基礎架構 擴展知識廣度,知識的深度,規範的開發體系 四個大的階段 Go語言基礎 微服務開發的(電商專案實戰) 自研微服務 自研然後重…

    個人 2025年11月25日
    27900
  • Go 工程師體系課程 006【學習筆記】

    專案結構說明:user-web 模組 user-web 是 joyshop_api 專案中的使用者服務 Web 層模組,負責處理使用者相關的 HTTP 請求、參數驗證、業務路由以及呼叫後端介面等功能。以下是目錄結構說明: user-web/ ├── api/ # 控制器層,定義業務介面處理邏輯 ├── config/ # 配置模組,包含系統配置結構體及讀取邏輯 …

    個人 2025年11月25日
    21500
  • TS珠峰 002【學習筆記】

    泛型 /* * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git &a…

    個人 2025年3月27日
    1.5K00
  • 從0到1落地微前端架構 001【學習筆記】

    微前端 js 隔離css 隔離元素隔離生命週期預載入資料通訊應用程式跳轉多層巢狀 說明 使用的是 Mermaid 的 flowchart 語法,Markdown 渲染器如 Typora、VitePress、一些 Git 平台都支援。 保留了: 基座應用 main-vue3 各子應用:child-nuxt2-home、child-vue2-job、child-vu…

    2025年4月20日
    1.5K00
  • Go 工程師體系課 004【學習筆記】

    需求分析 後台管理系統 商品管理 商品列表 商品分類 品牌管理 品牌分類 訂單管理 訂單列表 使用者資訊管理 使用者列表 使用者地址 使用者留言 輪播圖管理 電商系統 登入頁面 首頁 商品搜尋 商品分類導覽 輪播圖展示 推薦商品展示 商品詳情頁 商品圖片展示 商品描述 商品規格選擇 加入購物車 購物車 商品列表 數量調整 刪除商品 結帳功能 使用者中心 訂單中心 我的…

    2025年11月25日
    21400
簡體中文 繁體中文 English
歡迎🌹 Coding never stops, keep learning! 💡💻 光臨🌹