概述
定義
字符串就是零個或多個排在一起的字符营密,放在單引號或雙引號之中。
'abc'
"abc"
單引號字符串的內(nèi)部冰蘑,可以使用雙引號和泌。雙引號字符串的內(nèi)部,可以使用單引號祠肥。
'key = "value"'
"It's a long journey"
上面兩個都是合法的字符串武氓。
如果要在單引號字符串的內(nèi)部,使用單引號仇箱,就必須在內(nèi)部的單引號前面加上反斜杠县恕,用來轉(zhuǎn)義。雙引號字符串內(nèi)部使用雙引號剂桥,也是如此忠烛。
'Did she say \'Hello\'?'
// "Did she say 'Hello'?"
"Did she say \"Hello\"?"
// "Did she say "Hello"?"
由于 HTML 語言的屬性值使用雙引號,所以很多項目約定 JavaScript 語言的字符串只使用單引號权逗,本教程遵守這個約定美尸。當(dāng)然,只使用雙引號也完全可以斟薇。重要的是堅持使用一種風(fēng)格师坎,不要一會使用單引號表示字符串,一會又使用雙引號表示堪滨。
字符串默認(rèn)只能寫在一行內(nèi)胯陋,分成多行將會報錯。
'a
b
c'
// SyntaxError: Unexpected token ILLEGAL
上面代碼將一個字符串分成三行椿猎,JavaScript 就會報錯惶岭。
如果長字符串必須分成多行寿弱,可以在每一行的尾部使用反斜杠犯眠。
var longString = 'Long \
long \
long \
string';
longString
// "Long long long string"
上面代碼表示,加了反斜杠以后症革,原來寫在一行的字符串筐咧,可以分成多行書寫。但是,輸出的時候還是單行量蕊,效果與寫在同一行完全一樣铺罢。注意,反斜杠的后面必須是換行符残炮,而不能有其他字符(比如空格)韭赘,否則會報錯。
連接運算符(+
)可以連接多個單行字符串势就,將長字符串拆成多行書寫泉瞻,輸出的時候也是單行。
var longString = 'Long '
+ 'long '
+ 'long '
+ 'string';
如果想輸出多行字符串苞冯,有一種利用多行注釋的變通方法袖牙。
(function () { /*
line 1
line 2
line 3
*/}).toString().split('\n').slice(1, -1).join('\n')
// "line 1
// line 2
// line 3"
上面的例子中,輸出的字符串就是多行舅锄。
轉(zhuǎn)義
反斜杠(\)在字符串內(nèi)有特殊含義鞭达,用來表示一些特殊字符,所以又稱為轉(zhuǎn)義符皇忿。
需要用反斜杠轉(zhuǎn)義的特殊字符畴蹭,主要有下面這些。
-
\0
:null(\u0000
) -
\b
:后退鍵(\u0008
) -
\f
:換頁符(\u000C
) -
\n
:換行符(\u000A
) -
\r
:回車鍵(\u000D
) -
\t
:制表符(\u0009
) -
\v
:垂直制表符(\u000B
) -
\'
:單引號(\u0027
) -
\"
:雙引號(\u0022
) -
\\
:反斜杠(\u005C
)
上面這些字符前面加上反斜杠禁添,都表示特殊含義撮胧。
console.log('1\n2')
// 1
// 2
上面代碼中,\n
表示換行老翘,輸出的時候就分成了兩行芹啥。
反斜杠還有三種特殊用法。
(1)\HHH
反斜杠后面緊跟三個八進制數(shù)(000
到377
)铺峭,代表一個字符墓怀。HHH
對應(yīng)該字符的 Unicode 碼點,比如\251
表示版權(quán)符號卫键。顯然傀履,這種方法只能輸出256種字符。
(2)\xHH
\x
后面緊跟兩個十六進制數(shù)(00
到FF
)莉炉,代表一個字符钓账。HH
對應(yīng)該字符的 Unicode 碼點,比如\xA9
表示版權(quán)符號絮宁。這種方法也只能輸出256種字符梆暮。
(3)\uXXXX
\u
后面緊跟四個十六進制數(shù)(0000
到FFFF
),代表一個字符绍昂。HHHH
對應(yīng)該字符的 Unicode 碼點啦粹,比如\u00A9
表示版權(quán)符號偿荷。
下面是這三種字符特殊寫法的例子。
'\251' // "?"
'\xA9' // "?"
'\u00A9' // "?"
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
如果在非特殊字符前面使用反斜杠唠椭,則反斜杠會被省略跳纳。
'\a'
// "a"
上面代碼中,a
是一個正常字符贪嫂,前面加反斜杠沒有特殊含義寺庄,反斜杠會被自動省略。
如果字符串的正常內(nèi)容之中力崇,需要包含反斜杠铣揉,則反斜杠前面需要再加一個反斜杠,用來對自身轉(zhuǎn)義餐曹。
"Prev \\ Next"
// "Prev \ Next"
字符串與數(shù)組
字符串可以被視為字符數(shù)組逛拱,因此可以使用數(shù)組的方括號運算符,用來返回某個位置的字符(位置編號從0開始)台猴。
var s = 'hello';
s[0] // "h"
s[1] // "e"
s[4] // "o"
// 直接對字符串使用方括號運算符
'hello'[1] // "e"
如果方括號中的數(shù)字超過字符串的長度朽合,或者方括號中根本不是數(shù)字,則返回undefined
饱狂。
'abc'[3] // undefined
'abc'[-1] // undefined
'abc'['x'] // undefined
但是曹步,字符串與數(shù)組的相似性僅此而已。實際上休讳,無法改變字符串之中的單個字符讲婚。
var s = 'hello';
delete s[0];
s // "hello"
s[1] = 'a';
s // "hello"
s[5] = '!';
s // "hello"
上面代碼表示,字符串內(nèi)部的單個字符無法改變和增刪俊柔,這些操作會默默地失敗筹麸。
length 屬性
length
屬性返回字符串的長度,該屬性也是無法改變的雏婶。
var s = 'hello';
s.length // 5
s.length = 3;
s.length // 5
s.length = 7;
s.length // 5
上面代碼表示字符串的length
屬性無法改變物赶,但是不會報錯。
字符集
JavaScript 使用 Unicode 字符集留晚。JavaScript 引擎內(nèi)部酵紫,所有字符都用 Unicode 表示。
JavaScript 不僅以 Unicode 儲存字符错维,還允許直接在程序中使用 Unicode 碼點表示字符奖地,即將字符寫成\uxxxx
的形式,其中xxxx
代表該字符的 Unicode 碼點赋焕。比如参歹,\u00A9
代表版權(quán)符號。
var s = '\u00A9';
s // "?"
解析代碼的時候宏邮,JavaScript 會自動識別一個字符是字面形式表示泽示,還是 Unicode 形式表示。輸出給用戶的時候蜜氨,所有字符都會轉(zhuǎn)成字面形式械筛。
var f\u006F\u006F = 'abc';
foo // "abc"
上面代碼中,第一行的變量名foo
是 Unicode 形式表示飒炎,第二行是字面形式表示埋哟。JavaScript 會自動識別。
我們還需要知道郎汪,每個字符在 JavaScript 內(nèi)部都是以16位(即2個字節(jié))的 UTF-16 格式儲存赤赊。也就是說,JavaScript 的單位字符長度固定為16位長度煞赢,即2個字節(jié)抛计。
但是,UTF-16 有兩種長度:對于碼點在U+0000
到U+FFFF
之間的字符照筑,長度為16位(即2個字節(jié))吹截;對于碼點在U+10000
到U+10FFFF
之間的字符,長度為32位(即4個字節(jié))凝危,而且前兩個字節(jié)在0xD800
到0xDBFF
之間波俄,后兩個字節(jié)在0xDC00
到0xDFFF
之間。舉例來說蛾默,碼點U+1D306
對應(yīng)的字符為??懦铺,
它寫成 UTF-16 就是0xD834 0xDF06
。
JavaScript 對 UTF-16 的支持是不完整的支鸡,由于歷史原因冬念,只支持兩字節(jié)的字符,不支持四字節(jié)的字符牧挣。這是因為 JavaScript 第一版發(fā)布的時候刘急,Unicode 的碼點只編到U+FFFF
,因此兩字節(jié)足夠表示了浸踩。后來叔汁,Unicode 納入的字符越來越多,出現(xiàn)了四字節(jié)的編碼检碗。但是据块,JavaScript 的標(biāo)準(zhǔn)此時已經(jīng)定型了,統(tǒng)一將字符長度限制在兩字節(jié)折剃,導(dǎo)致無法識別四字節(jié)的字符另假。上一節(jié)的那個四字節(jié)字符??
,瀏覽器會正確識別這是一個字符怕犁,但是 JavaScript 無法識別边篮,會認(rèn)為這是兩個字符己莺。
'??'.length // 2
上面代碼中,JavaScript 認(rèn)為??
的長度為2戈轿,而不是1凌受。
總結(jié)一下,對于碼點在U+10000
到U+10FFFF
之間的字符思杯,JavaScript 總是認(rèn)為它們是兩個字符(length
屬性為2)胜蛉。所以處理的時候,必須把這一點考慮在內(nèi)色乾,也就是說誊册,JavaScript 返回的字符串長度可能是不正確的。
Base64 轉(zhuǎn)碼
有時暖璧,文本里面包含一些不可打印的符號案怯,比如 ASCII 碼0到31的符號都無法打印出來,這時可以使用 Base64 編碼澎办,將它們轉(zhuǎn)成可以打印的字符殴泰。另一個場景是,有時需要以文本格式傳遞二進制數(shù)據(jù)浮驳,那么也可以使用 Base64 編碼悍汛。
所謂 Base64 就是一種編碼方法,可以將任意值轉(zhuǎn)成 0~9至会、A~Z离咐、a-z、+
和/
這64個字符組成的可打印字符奉件。使用它的主要目的宵蛀,不是為了加密,而是為了不出現(xiàn)特殊字符县貌,簡化程序的處理术陶。
JavaScript 原生提供兩個 Base64 相關(guān)的方法。
-
btoa()
:任意值轉(zhuǎn)為 Base64 編碼 -
atob()
:Base64 編碼轉(zhuǎn)為原來的值
var string = 'Hello World!';
btoa(string) // "SGVsbG8gV29ybGQh"
atob('SGVsbG8gV29ybGQh') // "Hello World!"
注意煤痕,這兩個方法不適合非 ASCII 碼的字符梧宫,會報錯。
btoa('你好') // 報錯
要將非 ASCII 碼字符轉(zhuǎn)為 Base64 編碼摆碉,必須中間插入一個轉(zhuǎn)碼環(huán)節(jié)塘匣,再使用這兩個方法。
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
參考鏈接
- Mathias Bynens, JavaScript’s internal character encoding: UCS-2 or UTF-16?
- Mathias Bynens, JavaScript has a Unicode problem
- Mozilla Developer Network, Window.btoa