# String 對象
## 概述
`String`對象是 JavaScript 原生提供的三個包裝對象之一,用來生成字符串對象。
```javascript
var s1 = 'abc';
var s2 = new String('abc');
typeof s1 // "string"
typeof s2 // "object"
s2.valueOf() // "abc"
```
上面代碼中,變量`s1`是字符串,`s2`是對象。由于`s2`是字符串對象,`s2.valueOf`方法返回的就是它所對應的原始字符串。
字符串對象是一個類似數組的對象(很像數組,但不是數組)。
```javascript
new String('abc')
// String {0: "a", 1: "b", 2: "c", length: 3}
(new String('abc'))[1] // "b"
```
上面代碼中,字符串`abc`對應的字符串對象,有數值鍵(`0`、`1`、`2`)和`length`屬性,所以可以像數組那樣取值。
除了用作構造函數,`String`對象還可以當作工具方法使用,將任意類型的值轉為字符串。
```javascript
String(true) // "true"
String(5) // "5"
```
上面代碼將布爾值`true`和數值`5`,分別轉換為字符串。
## 靜態方法
### String.fromCharCode()
`String`對象提供的靜態方法(即定義在對象本身,而不是定義在對象實例的方法),主要是`String.fromCharCode()`。該方法的參數是一個或多個數值,代表 Unicode 碼點,返回值是這些碼點組成的字符串。
```javascript
String.fromCharCode() // ""
String.fromCharCode(97) // "a"
String.fromCharCode(104, 101, 108, 108, 111)
// "hello"
```
上面代碼中,`String.fromCharCode`方法的參數為空,就返回空字符串;否則,返回參數對應的 Unicode 字符串。
注意,該方法不支持 Unicode 碼點大于`0xFFFF`的字符,即傳入的參數不能大于`0xFFFF`(即十進制的 65535)。
```javascript
String.fromCharCode(0x20BB7)
// "?"
String.fromCharCode(0x20BB7) === String.fromCharCode(0x0BB7)
// true
```
上面代碼中,`String.fromCharCode`參數`0x20BB7`大于`0xFFFF`,導致返回結果出錯。`0x20BB7`對應的字符是漢字`??`,但是返回結果卻是另一個字符(碼點`0x0BB7`)。這是因為`String.fromCharCode`發現參數值大于`0xFFFF`,就會忽略多出的位(即忽略`0x20BB7`里面的`2`)。
這種現象的根本原因在于,碼點大于`0xFFFF`的字符占用四個字節,而 JavaScript 默認支持兩個字節的字符。這種情況下,必須把`0x20BB7`拆成兩個字符表示。
```javascript
String.fromCharCode(0xD842, 0xDFB7)
// "??"
```
上面代碼中,`0x20BB7`拆成兩個字符`0xD842`和`0xDFB7`(即兩個兩字節字符,合成一個四字節字符),就能得到正確的結果。碼點大于`0xFFFF`的字符的四字節表示法,由 UTF-16 編碼方法決定。
## 實例屬性
### String.prototype.length
字符串實例的`length`屬性返回字符串的長度。
```javascript
'abc'.length // 3
```
## 實例方法
### String.prototype.charAt()
`charAt`方法返回指定位置的字符,參數是從`0`開始編號的位置。
```javascript
var s = new String('abc');
s.charAt(1) // "b"
s.charAt(s.length - 1) // "c"
```
這個方法完全可以用數組下標替代。
```javascript
'abc'.charAt(1) // "b"
'abc'[1] // "b"
```
如果參數為負數,或大于等于字符串的長度,`charAt`返回空字符串。
```javascript
'abc'.charAt(-1) // ""
'abc'.charAt(3) // ""
```
### String.prototype.charCodeAt()
`charCodeAt()`方法返回字符串指定位置的 Unicode 碼點(十進制表示),相當于`String.fromCharCode()`的逆操作。
```javascript
'abc'.charCodeAt(1) // 98
```
上面代碼中,`abc`的`1`號位置的字符是`b`,它的 Unicode 碼點是`98`。
如果沒有任何參數,`charCodeAt`返回首字符的 Unicode 碼點。
```javascript
'abc'.charCodeAt() // 97
```
如果參數為負數,或大于等于字符串的長度,`charCodeAt`返回`NaN`。
```javascript
'abc'.charCodeAt(-1) // NaN
'abc'.charCodeAt(4) // NaN
```
注意,`charCodeAt`方法返回的 Unicode 碼點不會大于65536(0xFFFF),也就是說,只返回兩個字節的字符的碼點。如果遇到碼點大于 65536 的字符(四個字節的字符),必須連續使用兩次`charCodeAt`,不僅讀入`charCodeAt(i)`,還要讀入`charCodeAt(i+1)`,將兩個值放在一起,才能得到準確的字符。
### String.prototype.concat()
`concat`方法用于連接兩個字符串,返回一個新字符串,不改變原字符串。
```javascript
var s1 = 'abc';
var s2 = 'def';
s1.concat(s2) // "abcdef"
s1 // "abc"
```
該方法可以接受多個參數。
```javascript
'a'.concat('b', 'c') // "abc"
```
如果參數不是字符串,`concat`方法會將其先轉為字符串,然后再連接。
```javascript
var one = 1;
var two = 2;
var three = '3';
''.concat(one, two, three) // "123"
one + two + three // "33"
```
上面代碼中,`concat`方法將參數先轉成字符串再連接,所以返回的是一個三個字符的字符串。作為對比,加號運算符在兩個運算數都是數值時,不會轉換類型,所以返回的是一個兩個字符的字符串。
### String.prototype.slice()
`slice()`方法用于從原字符串取出子字符串并返回,不改變原字符串。它的第一個參數是子字符串的開始位置,第二個參數是子字符串的結束位置(不含該位置)。
```javascript
'JavaScript'.slice(0, 4) // "Java"
```
如果省略第二個參數,則表示子字符串一直到原字符串結束。
```javascript
'JavaScript'.slice(4) // "Script"
```
如果參數是負值,表示從結尾開始倒數計算的位置,即該負值加上字符串長度。
```javascript
'JavaScript'.slice(-6) // "Script"
'JavaScript'.slice(0, -6) // "Java"
'JavaScript'.slice(-2, -1) // "p"
```
如果第一個參數大于第二個參數(正數情況下),`slice()`方法返回一個空字符串。
```javascript
'JavaScript'.slice(2, 1) // ""
```
### String.prototype.substring()
`substring`方法用于從原字符串取出子字符串并返回,不改變原字符串,跟`slice`方法很相像。它的第一個參數表示子字符串的開始位置,第二個位置表示結束位置(返回結果不含該位置)。
```javascript
'JavaScript'.substring(0, 4) // "Java"
```
如果省略第二個參數,則表示子字符串一直到原字符串的結束。
```javascript
'JavaScript'.substring(4) // "Script"
```
如果第一個參數大于第二個參數,`substring`方法會自動更換兩個參數的位置。
```javascript
'JavaScript'.substring(10, 4) // "Script"
// 等同于
'JavaScript'.substring(4, 10) // "Script"
```
上面代碼中,調換`substring`方法的兩個參數,都得到同樣的結果。
如果參數是負數,`substring`方法會自動將負數轉為0。
```javascript
'JavaScript'.substring(-3) // "JavaScript"
'JavaScript'.substring(4, -3) // "Java"
```
上面代碼中,第二個例子的參數`-3`會自動變成`0`,等同于`'JavaScript'.substring(4, 0)`。由于第二個參數小于第一個參數,會自動互換位置,所以返回`Java`。
由于這些規則違反直覺,因此不建議使用`substring`方法,應該優先使用`slice`。
### String.prototype.substr()
`substr`方法用于從原字符串取出子字符串并返回,不改變原字符串,跟`slice`和`substring`方法的作用相同。
`substr`方法的第一個參數是子字符串的開始位置(從0開始計算),第二個參數是子字符串的長度。
```javascript
'JavaScript'.substr(4, 6) // "Script"
```
如果省略第二個參數,則表示子字符串一直到原字符串的結束。
```javascript
'JavaScript'.substr(4) // "Script"
```
如果第一個參數是負數,表示倒數計算的字符位置。如果第二個參數是負數,將被自動轉為0,因此會返回空字符串。
```javascript
'JavaScript'.substr(-6) // "Script"
'JavaScript'.substr(4, -1) // ""
```
上面代碼中,第二個例子的參數`-1`自動轉為`0`,表示子字符串長度為`0`,所以返回空字符串。
### String.prototype.indexOf(),String.prototype.lastIndexOf()
`indexOf`方法用于確定一個字符串在另一個字符串中第一次出現的位置,返回結果是匹配開始的位置。如果返回`-1`,就表示不匹配。
```javascript
'hello world'.indexOf('o') // 4
'JavaScript'.indexOf('script') // -1
```
`indexOf`方法還可以接受第二個參數,表示從該位置開始向后匹配。
```javascript
'hello world'.indexOf('o', 6) // 7
```
`lastIndexOf`方法的用法跟`indexOf`方法一致,主要的區別是`lastIndexOf`從尾部開始匹配,`indexOf`則是從頭部開始匹配。
```javascript
'hello world'.lastIndexOf('o') // 7
```
另外,`lastIndexOf`的第二個參數表示從該位置起向前匹配。
```javascript
'hello world'.lastIndexOf('o', 6) // 4
```
### String.prototype.trim()
`trim`方法用于去除字符串兩端的空格,返回一個新字符串,不改變原字符串。
```javascript
' hello world '.trim()
// "hello world"
```
該方法去除的不僅是空格,還包括制表符(`\t`、`\v`)、換行符(`\n`)和回車符(`\r`)。
```javascript
'\r\nabc \t'.trim() // 'abc'
```
### String.prototype.toLowerCase(),String.prototype.toUpperCase()
`toLowerCase`方法用于將一個字符串全部轉為小寫,`toUpperCase`則是全部轉為大寫。它們都返回一個新字符串,不改變原字符串。
```javascript
'Hello World'.toLowerCase()
// "hello world"
'Hello World'.toUpperCase()
// "HELLO WORLD"
```
### String.prototype.match()
`match`方法用于確定原字符串是否匹配某個子字符串,返回一個數組,成員為匹配的第一個字符串。如果沒有找到匹配,則返回`null`。
```javascript
'cat, bat, sat, fat'.match('at') // ["at"]
'cat, bat, sat, fat'.match('xt') // null
```
返回的數組還有`index`屬性和`input`屬性,分別表示匹配字符串開始的位置和原始字符串。
```javascript
var matches = 'cat, bat, sat, fat'.match('at');
matches.index // 1
matches.input // "cat, bat, sat, fat"
```
`match`方法還可以使用正則表達式作為參數,詳見《正則表達式》一章。
### String.prototype.search(),String.prototype.replace()
`search`方法的用法基本等同于`match`,但是返回值為匹配的第一個位置。如果沒有找到匹配,則返回`-1`。
```javascript
'cat, bat, sat, fat'.search('at') // 1
```
`search`方法還可以使用正則表達式作為參數,詳見《正則表達式》一節。
`replace`方法用于替換匹配的子字符串,一般情況下只替換第一個匹配(除非使用帶有`g`修飾符的正則表達式)。
```javascript
'aaa'.replace('a', 'b') // "baa"
```
`replace`方法還可以使用正則表達式作為參數,詳見《正則表達式》一節。
### String.prototype.split()
`split`方法按照給定規則分割字符串,返回一個由分割出來的子字符串組成的數組。
```javascript
'a|b|c'.split('|') // ["a", "b", "c"]
```
如果分割規則為空字符串,則返回數組的成員是原字符串的每一個字符。
```javascript
'a|b|c'.split('') // ["a", "|", "b", "|", "c"]
```
如果省略參數,則返回數組的唯一成員就是原字符串。
```javascript
'a|b|c'.split() // ["a|b|c"]
```
如果滿足分割規則的兩個部分緊鄰著(即兩個分割符中間沒有其他字符),則返回數組之中會有一個空字符串。
```javascript
'a||c'.split('|') // ['a', '', 'c']
```
如果滿足分割規則的部分處于字符串的開頭或結尾(即它的前面或后面沒有其他字符),則返回數組的第一個或最后一個成員是一個空字符串。
```javascript
'|b|c'.split('|') // ["", "b", "c"]
'a|b|'.split('|') // ["a", "b", ""]
```
`split`方法還可以接受第二個參數,限定返回數組的最大成員數。
```javascript
'a|b|c'.split('|', 0) // []
'a|b|c'.split('|', 1) // ["a"]
'a|b|c'.split('|', 2) // ["a", "b"]
'a|b|c'.split('|', 3) // ["a", "b", "c"]
'a|b|c'.split('|', 4) // ["a", "b", "c"]
```
上面代碼中,`split`方法的第二個參數,決定了返回數組的成員數。
`split`方法還可以使用正則表達式作為參數,詳見《正則表達式》一節。
### String.prototype.localeCompare()
`localeCompare`方法用于比較兩個字符串。它返回一個整數,如果小于0,表示第一個字符串小于第二個字符串;如果等于0,表示兩者相等;如果大于0,表示第一個字符串大于第二個字符串。
```javascript
'apple'.localeCompare('banana') // -1
'apple'.localeCompare('apple') // 0
```
該方法的最大特點,就是會考慮自然語言的順序。舉例來說,正常情況下,大寫的英文字母小于小寫字母。
```javascript
'B' > 'a' // false
```
上面代碼中,字母`B`小于字母`a`。因為 JavaScript 采用的是 Unicode 碼點比較,`B`的碼點是66,而`a`的碼點是97。
但是,`localeCompare`方法會考慮自然語言的排序情況,將`B`排在`a`的前面。
```javascript
'B'.localeCompare('a') // 1
```
上面代碼中,`localeCompare`方法返回整數1,表示`B`較大。
`localeCompare`還可以有第二個參數,指定所使用的語言(默認是英語),然后根據該語言的規則進行比較。
```javascript
'?'.localeCompare('z', 'de') // -1
'?'.localeCompare('z', 'sv') // 1
```
上面代碼中,`de`表示德語,`sv`表示瑞典語。德語中,`?`小于`z`,所以返回`-1`;瑞典語中,`?`大于`z`,所以返回`1`。
## 參考鏈接
- Ariya Hidayat, [JavaScript String: substring, substr, slice](http://ariya.ofilabs.com/2014/02/javascript-string-substring-substr-slice.html)
- 前言
- 入門篇
- 導論
- 歷史
- 基本語法
- 數據類型
- 概述
- null,undefined 和布爾值
- 數值
- 字符串
- 對象
- 函數
- 數組
- 運算符
- 算術運算符
- 比較運算符
- 布爾運算符
- 二進制位運算符
- 其他運算符,運算順序
- 語法專題
- 數據類型的轉換
- 錯誤處理機制
- 編程風格
- console 對象與控制臺
- 標準庫
- Object 對象
- 屬性描述對象
- Array 對象
- 包裝對象
- Boolean 對象
- Number 對象
- String 對象
- Math 對象
- Date 對象
- RegExp 對象
- JSON 對象
- 面向對象編程
- 實例對象與 new 命令
- this 關鍵字
- 對象的繼承
- Object 對象的相關方法
- 嚴格模式
- 異步操作
- 概述
- 定時器
- Promise 對象
- DOM
- 概述
- Node 接口
- NodeList 接口,HTMLCollection 接口
- ParentNode 接口,ChildNode 接口
- Document 節點
- Element 節點
- 屬性的操作
- Text 節點和 DocumentFragment 節點
- CSS 操作
- Mutation Observer API
- 事件
- EventTarget 接口
- 事件模型
- Event 對象
- 鼠標事件
- 鍵盤事件
- 進度事件
- 表單事件
- 觸摸事件
- 拖拉事件
- 其他常見事件
- GlobalEventHandlers 接口
- 瀏覽器模型
- 瀏覽器模型概述
- window 對象
- Navigator 對象,Screen 對象
- Cookie
- XMLHttpRequest 對象
- 同源限制
- CORS 通信
- Storage 接口
- History 對象
- Location 對象,URL 對象,URLSearchParams 對象
- ArrayBuffer 對象,Blob 對象
- File 對象,FileList 對象,FileReader 對象
- 表單,FormData 對象
- IndexedDB API
- Web Worker
- 附錄:網頁元素接口
- a
- img
- form
- input
- button
- option
- video,audio