(JS基礎)String 類型

咱們對字符串類型的數據並不會陌生。let str = 'value'就是一個最簡單的生成字符串例子。javascript

咱們還能夠經過String(thing)new String(thing)將任何類型的數據轉化成字符串。注意,new String(thing)會生成一個String類型的對象將字符串包裹。html

例如,把一個空對象傳入,String({})返回的值爲"[object Object]",這裏不得不提的就是,其餘類型默認的toString()方法本質就是調用String({})java

字符串量能直接使用String的屬性和方法,如'string'.toLowerCase()。其實語言內部會將'string'封裝成對象,再執行相應的方法,最後字符串對象使用valueOf()toString()方法獲得字符串的值。正則表達式


屬性

經常使用屬性只有一個:length,返回字符串的長度
數據庫

方法

如下介紹的,除了String​.raw()爲靜態方法,其餘都是字符串對象的方法。全部的字符串方法都不會對原字符串修改,都是返回一個新的字符串或結果。數組

拼接/補全

查詢

截取

  • slice(beginSlice[, endSlice]):返回從原字符串截取指定索引的片斷beginSlice表示做爲開始字符的索引,endSlice表示結束位置的索引,負數表示從後數起。
  • substring(indexStart[, indexEnd])與slice()基本一致,但indexEnd不能爲負數。
  • split([separator[, limit]]):使用指定的分隔符字符串將原字符串分割成字符串數組separator表示做爲分隔符的字符串或正則表達式;limit表示字符串數組的最大長度。
  • trim():返回一個將原字符的兩端刪除空白字符
  • trim​Right():返回一個將原字符的右端刪除空白字符
  • trim​Left():返回一個將原字符的左端刪除空白字符
  • chartAt(index):從原字符串中返回指定索引的字符
  • replace(regexp|substr, newSubStr|function)返回原字符串以特定規則被替換後的字符串。當前字符串不變。

轉換大小寫

字符碼點

  • normalize([form]):按照指定的一種 Unicode 正規形式將當前字符串正規化form默認爲 "NFC"。例子:'\u01D1'.normalize() === '\u004F\u030C'.normalize();  // true
  • charCodeAt(index):返回指定索引的 UTF-16 代碼單元值的數字;若是索引超出範圍,則返回NaN。對於都是"基本平面"的字符串,索引值與其所在位置相同;但對於含有"輔助平面"的字符串來講就要注意,如𝌆爲 4 字節字符,須要兩個 UTF-16 代碼單元表示,'𝌆a'.charCodeAt(2)的值爲 97 ,而非NaN,而索引 1 和 2 的值分別爲𝌆的高位和低位的碼點數值。
  • codePointAt(index):就我我的測試來看,charCodeAt()方法返回的結果一致,除了索引超出範圍返回的是undefined

內置迭代器([Symbol.iterator])

String對象內置Iterator對象,經過屬性[Symbol.iterator]獲取,在遍歷時調用,如for...of運算、展開運算符(...)等。bash

獲取迭代器
函數

let strIterator = 'abcde'[Symbol.iterator]();
console.log(strIterator.next().value);  // 'a'
console.log(strIterator.next().value);  // 'b'
console.log(strIterator.next().value);  // 'c'複製代碼

修改迭代器
測試

// 必須建立字符串對象
let str = new String('abcde');
// 原生迭代器效果
for (let i of str) {
  console.log(i);
}
// 打印結果: a b c d e
// 自定義迭代器函數
str[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
}
// 測試自定義迭代器
console.log(...str);  // 1 2 3複製代碼


字符串模板(Template literals)

字符串模板用"反引號"表示,即 ` `ui

基本用法

模板字符串內,字符串量能夠直接寫,${ }內執行JavaScrip代碼。用於生成一個帶運算的字符串結果。

let num1 = 123,
  num2 = 456;
let temp = `hello ${num1 + num2} world !`;
console.log(temp);    // "hello 579 world !"複製代碼

標籤模板(Tagged templates)用法

咱們通常調用函數的方式是fn(['hello ', 'world'], 999),函數名後用括號包裹參數。而標籤模板能夠這樣寫:fn`hello ${args}world`,函數名後直接跟``。注意,這兩種方式的參數是一致的。

分解:

${ }的模板字符串,內部實際上是被${}分割成多份。以`hello ${999}world${666} !`爲例:

` hello ${999} world ${666} ! `複製代碼

${ }的外面是字符串直接量,而${ }之間是 js 代碼。如此看來,字符串模板被分紅了 5 份,而字符串直接量會組成字符串數組,因此傳入函數時是 3 個參數,分別是['hello ', 'world', ' !']999666。下面給出簡單例子說明。

// 用於查看傳參狀況的函數
function fn() {
  console.log(arguments[0])
}
fn`hello ${999}world${666} !`;
// 下圖看結果複製代碼

String​.raw()

談到模板字符串,不得不談String對象的一個靜態方法:String​.raw()。通常都是以標籤函數的方式調用它,即String​.raw``,固然,你可使用普通函數的()方式傳參,只不過要按照上面額規則手動轉化一下。它的用途是獲取一個模板字符串的原始字面量值,簡單說就是把全部的反斜槓(\)轉義。

String.raw `Hi\u000A!`;      // "Hi\\u000A!"
String.raw `Hi\n${999}!`;    // "Hi\\n999!"
String.raw`\\`;              // "\\\\"
複製代碼


字符編碼與字符集

基本概念

  1. 字符,是各類文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。
  2. 字庫表,是一個至關於全部可讀或者可顯示字符的數據庫,字庫表決定了整個字符集可以展示表示的全部字符的範圍。其實就是字符的集合
  3. 編碼字符集,簡稱字符集,用一個編碼值code point(又稱碼點)來表示一個字符(即該字符在子庫表中的位置),這個值稱爲字符對應於編碼字符集(如:Unicode、ASCII)的序號。
  4. 字符編碼,是編碼字符集和實際存儲數值之間的轉換關係。

用商場儲物櫃爲例子。

字符,等於單個櫃箱,存放着咱們想看的內容。

整個儲物櫃就是字庫表

爲每一個櫃箱按順序貼上標籤後,整個儲物櫃就是編碼字符集,每一個數字(碼點)對應一個櫃箱(字符)。

咱們手上有一份查詢表格,但表格上只能寫二進制或十六進制的數字。以什麼樣的方式把儲物櫃上的數字對應到表格上(映射),就是字符編碼

ASCII

ASCII 既是字符集,也是字符編碼。用一個字節的長度存儲字符。自行百度,很少介紹。

Unicode

Unicode 是一個字符集,爲每一個符號指定一個編號,即"碼點"(code point)。其目標是將全世界全部的字符包含在一個集合裏,計算機只要支持這一個字符集,就能顯示全部的字符。

每一個區能夠存放 65536 個(216)字符,稱爲一個平面(plane)。

目前,一共有 17 個(25)平面,也就是說,整個 Unicode 字符集的大小如今是 221

最前面的 65536 個字符位,稱爲基本平面(縮寫 BMP ),它的碼點範圍是從 0 一直到 216-1 ,寫成 16 進制就是從 U+0000 ~ U+FFFF

剩下的字符都放在輔助平面(縮寫 SMP ),碼點範圍爲 U+010000 ~ U+10FFFF

UTF-32

UTF-32 是字符編碼方式,用固定長度的 4 字節表示一個字符,與 Unicode 字節內容一一對應碼點。例如:

U+597D = 0x0000 597D複製代碼

但缺點很明顯,浪費空間。HTML5 標準就明文規定,網頁不得編碼成UTF-32。

UTF-8

UTF-8 是一種變長的編碼方法,字符長度從 1 個字節到 4 個字節不等。越是經常使用的字符,字節越短,最前面的 128 個字符,只使用 1 個字節表示,與 ASCII 碼徹底相同。如,編碼範圍在0x0000 - 0x007F只佔用 1 字節,而0x010000 - 0x10FFFF要佔用 4 字節。是最多見的網頁編碼。

因爲 UTF-8 是變長的,若不直到其長度,連續的字符則沒法解析。如何判斷其長度,這就涉及它的編碼規則

  1. 對於單字節的符號,第一位爲 0 ,用二進制表示爲0xxx xxxx
  2. 對於n字節的符號(n>1),第一個字節的前n位都設爲1,第n+1位設爲0,後面字節的前兩位一概設爲10。剩下的沒有說起的二進制位,所有爲這個符號的unicode碼。

阮一峯的博文的圖表展現:

Unicode 符號範圍 (十六進制) UTF-8 編碼方式 (二進制) 字節
0000 0000-0000 007F 0xxxxxxx 1
0000 0080-0000 07FF 110xxxxx 10xxxxxx 2
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx 3
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4

圖表中x組合而成的就是實際的 Unicode 碼點。

UTF-16

UTF-16 編碼介於 UTF-32 與 UTF-8 之間,同時結合了定長和變長兩種編碼方法的特色。編碼規則就是,基本平面的字符佔用 2 個字節輔助平面的字符佔用 4 個字節

由於在基本平面內,從U+D800 ~ U+DFFF是一個空段,空間爲 211 ,即 2 個 210 。而一個輔助平面的字符須要的空間爲 220 ,恰好能夠拆分紅兩個空段內的字符,高位(H)映射在U+D800 ~ U+DBFF低位(L)映射在U+DC00 ~ U+DFFF。所以解決了 4 字節的字符的識別問題。

因此,對於基本平面,Unicode 與 UTF-16 碼相同。

對於輔助平面,Unicode 與 UTF-16 的轉化公式以下:

H = Math.floor((c-0x10000) / 0x400) + 0xD800
L = (c - 0x10000) % 0x400 + 0xDC00複製代碼

不難理解,輔助平面的碼點是從U+10000開始,則減去0x10000;上面提到高低位各佔 10 位,則除以0x400獲得的商和餘數則分別位高低位的起點值,最後高位加上基礎值0xD800,低位加上0xDC00獲得目標值。(內容總結自阮一峯的博文

JavaScript 使用的編碼方式

JavaScript 語言採用 Unicode 字符集,可是隻支持一種編碼方法,就是 UCS-2 。因爲歷史緣由(阮一峯的博文有介紹),UCS-2 只支持 2 字節的字符,4 字節的字符被當成 2 個 2 字節的字符解析。如今已經沒有 UCS-2 。

ES6 加強對 Unicode 的支持

  1. ES6 能夠自動識別 4 字節的碼點,如console.log('\ud834\udf06');  // 𝌆
  2. 容許直接用碼點表示Unicode字符,如'𝌆' === '\u{1d306}';  // true。2 字節的字符能夠省略{}
  3. ES6 新增了幾個專門處理 4 字節碼點的函數(看上方介紹)。
  4. ES6 的正則表達式提供了u修飾符,對正則表達式添加 4 字節碼點的支持。例子:/^.$/.test('𝌆');  // false/^.$/u.test('𝌆'); // true
相關文章
相關標籤/搜索