字串是 JavaScript 字元的不可變序列。每個字元都是一個 16 位元的 UTF-16 編碼單位。這表示單一 Unicode 字元由一個或兩個 JavaScript 字元表示。只要計算字元或分割字串(請參閱 第 24 章),您主要需要擔心兩個字元的案例。
單引號和雙引號都可以用來 界定字串文字:
'He said: "Hello"'
"He said: \"Hello\""
'Everyone\'s a winner'
"Everyone's a winner"
因此,您可以自由使用任何一種引號。不過,有幾個考量因素
如果您一致地使用引號,您的程式碼看起來會更簡潔。但是,有時不同的引號表示您不必跳脫,這可以證明您不那麼一致(例如,您通常可能使用單引號,但暫時切換到雙引號來撰寫前一個範例的最後一個)。
字串文字中的大多數字元 僅代表它們自己。反斜線用於 跳脫,並啟用數個特殊功能:
您可以透過使用反斜線跳脫行尾(換行字元,換行符)來將字串分佈在多行:
var
str
=
'written \
over \
multiple \
lines'
;
console
.
log
(
str
===
'written over multiple lines'
);
// true
另一種方法是使用 加號運算子來串接:
var
str
=
'written '
+
'over '
+
'multiple '
+
'lines'
;
這些 序列以反斜線開頭:
\b
是退格,\f
是換頁,\n
是換行,\r
是回車,\t
是水平定位標籤,\v
是垂直定位標籤。
表示自己的轉義字元:\'
是單引號,\"
是雙引號,\\
是反斜線。除了 b f n r t v x u
和十進位數字之外的所有字元也都表示自己。以下是兩個範例
> '\"' '"' > '\q' 'q'
\0
表示。
\xHH
(HH
是兩個十六進位數字)透過 ASCII 編碼指定字元。例如:
> '\x4D' 'M'
\uHHHH
(HHHH
是四個十六進位數字)指定 UTF-16 編碼單位(請參閱 第 24 章 Unicode 和 JavaScript)。以下是兩個範例
> '\u004D' 'M' > '\u03C0' 'π'
有兩個運算會傳回字串的第 n 個字元。[16] 請注意 JavaScript 沒有字元的特殊資料類型;這些運算會傳回字串
> 'abc'.charAt(1) 'b' > 'abc'[1] 'b'
有些舊瀏覽器不支援透過方括弧陣列式存取字元。
值 | 結果 |
|
|
|
|
布林值 |
|
| |
數字 | 數字以字串形式表示(例如, |
字串 | 與輸入相同(無需轉換) |
物件 | 呼叫 |
將任何值轉換為字串的三種最常見方式為:
| (以函數呼叫,而非建構函數) |
| |
| (不適用於 |
我偏好 String()
,因為它較具描述性。以下是幾個範例
> String(false) 'false' > String(7.35) '7.35' > String({ first: 'John', last: 'Doe' }) '[object Object]' > String([ 'a', 'b', 'c' ]) 'a,b,c'
請注意,對於顯示資料,JSON.stringify()
(JSON.stringify(value, replacer?, space?)) 通常比正規轉換為字串效果更好:
> console.log(JSON.stringify({ first: 'John', last: 'Doe' })) {"first":"John","last":"Doe"} > console.log(JSON.stringify([ 'a', 'b', 'c' ])) ["a","b","c"]
當然,您必須了解 JSON.stringify()
的限制,它並非總是顯示所有內容。例如,它會隱藏它無法處理的值的屬性(函數等)。好處是,其輸出可以由 eval()
解析,而且它可以將深度巢狀資料顯示為格式良好的樹狀結構。
考量到 JavaScript 自動轉換的頻率,令人遺憾的是轉換並非總是可反轉,特別是布林值:
> String(false) 'false' > Boolean('false') true
對於 undefined
和 null
,我們面臨類似的問題。
有兩種比較字串的方法。首先,您可以使用比較運算子: <
、>
、===
、<=
、>=
。 它們有以下缺點:
它們區分大小寫
> 'B' > 'A' // ok true > 'B' > 'a' // should be true false
它們無法妥善處理變音符號和重音符號
> 'ä' < 'b' // should be true false > 'é' < 'f' // should be true false
其次,您可以使用 String.prototype.localeCompare(other)
,它往往表現得更好,但並非總是受支援(請參閱 搜尋和比較 以取得詳細資料)。以下是 Firefox 主控台中的互動
> 'B'.localeCompare('A') 2 > 'B'.localeCompare('a') 2 > 'ä'.localeCompare('b') -2 > 'é'.localeCompare('f') -2
小於零的結果表示接收器「小於」引數。大於零的結果表示接收器「大於」引數。
有兩種主要方法可連接字串。
當運算元之一為字串時,+
算子會執行字串連接。如果您想在變數中收集字串片段,複合賦值運算元 +=
會很有用:
> var str = ''; > str += 'Say hello '; > str += 7; > str += ' times fast!'; > str 'Say hello 7 times fast!'
看起來先前的做法會在每次新增片段到 str
時建立一個新字串。較舊的 JavaScript 引擎會這樣做,這表示您可以先將所有片段收集到陣列中,最後再將它們連接起來,以提升字串連接效能:
> var arr = []; > arr.push('Say hello '); > arr.push(7); > arr.push(' times fast'); > arr.join('') 'Say hello 7 times fast'
不過,較新的引擎會透過 +
最佳化字串連接,並在內部使用類似的方法。因此,加號運算元在這些引擎上會比較快。
前者呼叫比較常見。
String.fromCharCode(codeUnit1, codeUnit2, ...)
會產生一個字串,其字元為 16 位元無號整數 codeUnit1
、codeUnit2
等指定的 UTF-16 編碼單位。例如:
> String.fromCharCode(97, 98, 99) 'abc'
如果您想將數字陣列轉換為字串,您可以透過 apply()
執行(請參閱 func.apply(thisValue, argArray))
> String.fromCharCode.apply(null, [97, 98, 99]) 'abc'
原始字串的所有方法都儲存在 String.prototype
中(請參閱 原始類型從包裝類型借用其方法)。接下來,我將說明它們如何用於原始字串,而不是 String
的實例。
下列方法從接收器擷取子字串
String.prototype.charAt(pos)
傳回一個字串,其中包含位置 pos
的字元。例如:
> 'abc'.charAt(1) 'b'
下列兩個表達式傳回相同的結果,但有些較舊的 JavaScript 引擎只支援 charAt()
來存取字元
str
.
charAt
(
n
)
str
[
n
]
String.prototype.charCodeAt(pos)
傳回位置 pos
的 JavaScript 字元(UTF-16 編碼單位;請參閱 第 24 章)的代碼(16 位元無符號整數)。
以下是 建立字元代碼陣列 的方式:
> 'abc'.split('').map(function (x) { return x.charCodeAt(0) }) [ 97, 98, 99 ]
charCodeAt()
的反函式是 String.fromCharCode()
。
String.prototype.slice(start, end?)
傳回從位置 start
開始到位置 end
(不含)的子字串。 兩個參數都可以是負數,然後字串的 length
會加到它們上面:
> 'abc'.slice(2) 'c' > 'abc'.slice(1, 2) 'b' > 'abc'.slice(-2) 'bc'
String.prototype.substring(start, end?)
slice()
,它可以處理負數位置,而且在各個瀏覽器中實作更一致。 String.prototype.split(separator?, limit?)
擷取接收器中由 separator
分隔的子字串,並將它們傳回陣列中。此方法有兩個參數:
separator
:字串或正規表示式。如果遺漏,會傳回完整的字串,並將其包在陣列中。
limit
:如果提供,傳回的陣列會包含最多 limit
個元素。
以下是一些範例
> 'a, b,c, d'.split(',') // string [ 'a', ' b', 'c', ' d' ] > 'a, b,c, d'.split(/,/) // simple regular expression [ 'a', ' b', 'c', ' d' ] > 'a, b,c, d'.split(/, */) // more complex regular expression [ 'a', 'b', 'c', 'd' ] > 'a, b,c, d'.split(/, */, 2) // setting a limit [ 'a', 'b' ] > 'test'.split() // no separator provided [ 'test' ]
如果有一個群組,則也會將匹配項傳回為陣列元素
> 'a, b , '.split(/(,)/) [ 'a', ',', ' b ', ',', ' ' ] > 'a, b , '.split(/ *(,) */) [ 'a', ',', 'b', ',', '' ]
使用 ''
(空字串)作為分隔符號,產生一個包含字串字元的陣列
> 'abc'.split('') [ 'a', 'b', 'c' ]
前一節是關於擷取子字串,本節是關於將給定的字串轉換成新的字串。這些方法通常如下使用:
var
str
=
str
.
trim
();
換句話說,原始字串在被(非破壞性地)轉換後會被捨棄
String.prototype.trim()
> '\r\nabc \t'.trim() 'abc'
String.prototype.concat(str1?, str2?, ...)
傳回接收者和 str1
、str2
等的串接:
> 'hello'.concat(' ', 'world', '!') 'hello world!'
String.prototype.toLowerCase()
建立一個新的 字串,其中所有原始字串的字元都轉換成小寫:
> 'MJÖLNIR'.toLowerCase() 'mjölnir'
String.prototype.toLocaleLowerCase()
toLowerCase()
相同,但會遵守目前區域設定的規則。根據 ECMAScript 規範:「只有在少數情況(例如土耳其語)中,該語言的規則與一般 Unicode 大小寫對應衝突時,才會有所不同。」 String.prototype.toUpperCase()
> 'mjölnir'.toUpperCase() 'MJÖLNIR'
String.prototype.toLocaleUpperCase()
toUpperCase()
相同,但會遵守目前區域設定的規則。 下列方法 用於搜尋和比較字串:
String.prototype.indexOf(searchString, position?)
從 position
(預設為 0)開始搜尋 searchString
。它會傳回找到 searchString
的位置,或找不到時傳回 –1
> 'aXaX'.indexOf('X') 1 > 'aXaX'.indexOf('X', 2) 3
請注意,在字串中尋找文字時,正規表示式也能發揮同樣的作用。例如,下列兩個表達式是等效的:
str
.
indexOf
(
'abc'
)
>=
0
/
abc
/
.
test
(
str
)
String.prototype.lastIndexOf(searchString, position?)
從 position
(預設為結尾)開始向後搜尋 searchString
。它會傳回找到 searchString
的位置,或找不到時傳回 –1:
> 'aXaX'.lastIndexOf('X') 3 > 'aXaX'.lastIndexOf('X', 2) 1
String.prototype.localeCompare(other)
執行字串與 other
的區域設定敏感 比較。它會傳回一個數字:
other
之前
other
other
之後
例如
> 'apple'.localeCompare('banana') -2 > 'apple'.localeCompare('apple') 0
並非所有 JavaScript 引擎都能正確實作此方法。有些僅根據比較運算子來實作。不過,ECMAScript 國際化 API(請參閱 ECMAScript 國際化 API)確實提供 Unicode 感知實作。亦即,如果引擎中提供該 API,則 localeCompare()
會運作。
如果支援,localeCompare()
會比比較運算子更適合用來比較字串。請參閱 比較字串 以取得更多資訊。
下列方法使用正規表示式
String.prototype.search(regexp)
(在 String.prototype.search:比對在哪個索引位置? 中有更詳細的說明)
傳回 regexp
在接收者中比對到的第一個索引(如果沒有比對到,則傳回 –1):
> '-yy-xxx-y-'.search(/x+/) 4
String.prototype.match(regexp)
(在 String.prototype.match:擷取群組或傳回所有比對到的子字串 中有更詳細的說明)
比對接收者與指定的正規表示式。如果 regexp
的旗標 /g
未設定,則會傳回第一個比對的比對物件:
> '-abb--aaab-'.match(/(a+)b/) [ 'ab', 'a', index: 1, input: '-abb--aaab-' ]
如果旗標 /g
已設定,則會在陣列中傳回所有完整的比對(群組 0)
> '-abb--aaab-'.match(/(a+)b/g) [ 'ab', 'aaab' ]
String.prototype.replace(search, replacement)
(在 String.prototype.replace:搜尋和取代 中有更詳細的說明)
搜尋 search
並以 replacement
取代。search
可以是字串或正規表示式,而 replacement
可以是字串或函式。除非您使用正規表示式作為 search
,且其旗標 /g
已設定,否則只會取代第一次出現的字串
> 'iixxxixx'.replace('i', 'o') 'oixxxixx' > 'iixxxixx'.replace(/i/, 'o') 'oixxxixx' > 'iixxxixx'.replace(/i/g, 'o') 'ooxxxoxx'
取代字串中的美元符號 ($
) 可讓您參考完整的比對或擷取的群組:
> 'iixxxixx'.replace(/i+/g, '($&)') // complete match '(ii)xxx(i)xx' > 'iixxxixx'.replace(/(i+)/g, '($1)') // group 1 '(ii)xxx(i)xx'
您也可以透過函式來計算取代
> function repl(all) { return '('+all.toUpperCase()+')' } > 'axbbyyxaa'.replace(/a+|b+/g, repl) '(A)x(BB)yyx(AA)'