咱們對字符串類型的數據並不會陌生。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()
爲靜態方法,其餘都是字符串對象的方法。全部的字符串方法都不會對原字符串修改,都是返回一個新的字符串或結果。數組
padString
表示用於填充的字符串,默認爲" "
。padString
表示用於填充的字符串,默認爲" "
。count
表示重複的次數。position
表示開始查找的索引,默認爲 0 。position
表示開始查找的索引,默認爲 0 。position
表示開始查找的索引,默認爲 0 。fromIndex
表示開始查找的索引。indexOf()
相似,不一樣的是,返回給定的字符串在原字符串的最後一次出現的索引值。beginSlice
表示做爲開始字符的索引,endSlice
表示結束位置的索引,負數表示從後數起。indexEnd
不能爲負數。separator
表示做爲分隔符的字符串或正則表達式;limit
表示字符串數組的最大長度。form
默認爲 "NFC
"。例子:'\u01D1'.normalize() === '\u004F\u030C'.normalize(); // true
。NaN
。對於都是"基本平面"的字符串,索引值與其所在位置相同;但對於含有"輔助平面"的字符串來講就要注意,如𝌆
爲 4 字節字符,須要兩個 UTF-16 代碼單元表示,'𝌆a'.charCodeAt(2)
的值爲 97 ,而非NaN
,而索引 1 和 2 的值分別爲𝌆
的高位和低位的碼點數值。charCodeAt()
方法返回的結果一致,除了索引超出範圍返回的是undefined
。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複製代碼
字符串模板用"反引號"表示,即 ` `
。ui
模板字符串內,字符串量能夠直接寫,${ }
內執行JavaScrip
代碼。用於生成一個帶運算的字符串結果。
let num1 = 123,
num2 = 456;
let temp = `hello ${num1 + num2} world !`;
console.log(temp); // "hello 579 world !"複製代碼
咱們通常調用函數的方式是fn(['hello ', 'world'], 999)
,函數名後用括號包裹參數。而標籤模板能夠這樣寫:fn`hello ${args}world`
,函數名後直接跟``
。注意,這兩種方式的參數是一致的。
分解:
帶${ }
的模板字符串,內部實際上是被${
和}
分割成多份。以`hello ${999}world${666} !`
爲例:
` hello ${999} world ${666} ! `複製代碼
${ }
的外面是字符串直接量,而${ }
之間是 js 代碼。如此看來,字符串模板被分紅了 5 份,而字符串直接量會組成字符串數組,因此傳入函數時是 3 個參數,分別是['hello ', 'world', ' !']
、999
、666
。下面給出簡單例子說明。
// 用於查看傳參狀況的函數
function fn() {
console.log(arguments[0])
}
fn`hello ${999}world${666} !`;
// 下圖看結果複製代碼
談到模板字符串,不得不談String
對象的一個靜態方法:String.raw()。通常都是以標籤函數的方式調用它,即String.raw``
,固然,你可使用普通函數的()
方式傳參,只不過要按照上面額規則手動轉化一下。它的用途是獲取一個模板字符串的原始字面量值,簡單說就是把全部的反斜槓(\
)轉義。
String.raw `Hi\u000A!`; // "Hi\\u000A!"
String.raw `Hi\n${999}!`; // "Hi\\n999!"
String.raw`\\`; // "\\\\"
複製代碼
code point
(又稱碼點)來表示一個字符(即該字符在子庫表中的位置),這個值稱爲字符對應於編碼字符集(如:Unicode、ASCII)的序號。用商場儲物櫃爲例子。
字符,等於單個櫃箱,存放着咱們想看的內容。
整個儲物櫃就是字庫表。
爲每一個櫃箱按順序貼上標籤後,整個儲物櫃就是編碼字符集,每一個數字(碼點)對應一個櫃箱(字符)。
咱們手上有一份查詢表格,但表格上只能寫二進制或十六進制的數字。以什麼樣的方式把儲物櫃上的數字對應到表格上(映射),就是字符編碼。
ASCII 既是字符集,也是字符編碼。用一個字節的長度存儲字符。自行百度,很少介紹。
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 是字符編碼方式,用固定長度的 4 字節表示一個字符,與 Unicode 字節內容一一對應碼點。例如:
U+597D = 0x0000 597D複製代碼
但缺點很明顯,浪費空間。HTML5 標準就明文規定,網頁不得編碼成UTF-32。
UTF-8 是一種變長的編碼方法,字符長度從 1 個字節到 4 個字節不等。越是經常使用的字符,字節越短,最前面的 128 個字符,只使用 1 個字節表示,與 ASCII 碼徹底相同。如,編碼範圍在0x0000 - 0x007F
只佔用 1 字節,而0x010000 - 0x10FFFF
要佔用 4 字節。是最多見的網頁編碼。
因爲 UTF-8 是變長的,若不直到其長度,連續的字符則沒法解析。如何判斷其長度,這就涉及它的編碼規則:
0xxx xxxx
。用阮一峯的博文的圖表展現:
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-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 語言採用 Unicode 字符集,可是隻支持一種編碼方法,就是 UCS-2 。因爲歷史緣由(阮一峯的博文有介紹),UCS-2 只支持 2 字節的字符,4 字節的字符被當成 2 個 2 字節的字符解析。如今已經沒有 UCS-2 。
ES6 加強對 Unicode 的支持:
console.log('\ud834\udf06'); // 𝌆
。'𝌆' === '\u{1d306}'; // true
。2 字節的字符能夠省略{}
。u
修飾符,對正則表達式添加 4 字節碼點的支持。例子:/^.$/.test('𝌆'); // false
,/^.$/u.test('𝌆'); // true
。