W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
字符串就是零個或多個排在一起的字符,放在單引號或雙引號之中。
'abc'
"abc"
單引號字符串的內(nèi)部,可以使用雙引號。雙引號字符串的內(nèi)部,可以使用單引號。
'key = "value"'
"It's a long journey"
上面兩個都是合法的字符串。
如果要在單引號字符串的內(nèi)部,使用單引號(或者在雙引號字符串的內(nèi)部,使用雙引號),就必須在內(nèi)部的單引號(或者雙引號)前面加上反斜杠,用來轉(zhuǎn)義。
'Did she say \'Hello\'?'
// "Did she say 'Hello'?"
"Did she say \"Hello\"?"
// "Did she say "Hello"?"
由于HTML語言的屬性值使用雙引號,所以很多項目約定JavaScript語言的字符串只使用單引號,本教程就遵守這個約定。當(dāng)然,只使用雙引號也完全可以。重要的是,堅持使用一種風(fē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"
上面的例子中,輸出的字符串就是多行。
反斜杠(\)在字符串內(nèi)有特殊含義,用來表示一些特殊字符,所以又稱為轉(zhuǎn)義符。
需要用反斜杠轉(zhuǎn)義的特殊字符,主要有下面這些:
\0
null(\u0000)\b
后退鍵(\u0008)\f
換頁符(\u000C)\n
換行符(\u000A)\r
回車鍵(\u000D)\t
制表符(\u0009)\v
垂直制表符(\u000B)\'
單引號(\u0027)\"
雙引號(\u0022)上面這些字符前面加上反斜杠,都表示特殊含義。
console.log('1\n2')
// 1
// 2
上面代碼中,\n
表示換行,輸出的時候就分成了兩行。
反斜杠還有三種特殊用法。
(1)\HHH
反斜杠后面緊跟三個八進(jìn)制數(shù)(000
到377
),代表一個字符。HHH
對應(yīng)該字符的Unicode碼點,比如\251
表示版權(quán)符號。顯然,這種方法只能輸出256種字符。
(2)\xHH
\x
后面緊跟兩個十六進(jìn)制數(shù)(00
到FF
),代表一個字符。HH
對應(yīng)該字符的Unicode碼點,比如\xA9
表示版權(quán)符號。這種方法也只能輸出256種字符。
(3)\uXXXX
\u
后面緊跟四個十六進(jìn)制數(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ù)組的方括號運算符,用來返回某個位置的字符(位置編號從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)部的單個字符無法改變和增刪,這些操作會默默地失敗。
字符串也無法直接使用數(shù)組的方法,必須通過call
方法間接使用。
var s = 'hello';
s.join(' ') // TypeError: s.join is not a function
Array.prototype.join.call(s, ' ') // "h e l l o"
上面代碼中,如果直接對字符串使用數(shù)組的join
方法,會報錯不存在該方法。但是,可以通過call
方法,間接對字符串使用join
方法。
不過,由于字符串是只讀的,那些會改變原數(shù)組的方法,比如push()
、sort()
、reverse()
、splice()
都對字符串無效,只有將字符串顯式轉(zhuǎn)為數(shù)組后才能使用,參見《標(biāo)準(zhǔn)庫》一章的數(shù)組部分。
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
。瀏覽器會正確將這四個字節(jié)識別為一個字符,但是JavaScript內(nèi)部的字符長度總是固定為16位,會把這四個字節(jié)視為兩個字符。
var s = '\uD834\uDF06';
s // "????"
s.length // 2
/^.$/.test(s) // false
s.charAt(0) // ""
s.charAt(1) // ""
s.charCodeAt(0) // 55348
s.charCodeAt(1) // 57094
上面代碼說明,對于于U+10000
到U+10FFFF
之間的字符,JavaScript總是視為兩個字符(字符的length
屬性為2),用來匹配單個字符的正則表達(dá)式會失?。↗avaScript認(rèn)為這里不止一個字符),charAt
方法無法返回單個字符,charCodeAt
方法返回每個字節(jié)對應(yīng)的十進(jìn)制值。
所以處理的時候,必須把這一點考慮在內(nèi)。對于4個字節(jié)的Unicode字符,假定C
是字符的Unicode編號,H
是前兩個字節(jié),L
是后兩個字節(jié),則它們之間的換算關(guān)系如下。
// 將大于U+FFFF的字符,從Unicode轉(zhuǎn)為UTF-16
H = Math.floor((C - 0x10000) / 0x400) + 0xD800
L = (C - 0x10000) % 0x400 + 0xDC00
// 將大于U+FFFF的字符,從UTF-16轉(zhuǎn)為Unicode
C = (H - 0xD800) * 0x400 + L - 0xDC00 + 0x10000
下面的正則表達(dá)式可以識別所有UTF-16字符。
([\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF])
由于JavaScript引擎(嚴(yán)格說是ES5規(guī)格)不能自動識別輔助平面(編號大于0xFFFF)的Unicode字符,導(dǎo)致所有字符串處理函數(shù)遇到這類字符,都會產(chǎn)生錯誤的結(jié)果(詳見《標(biāo)準(zhǔn)庫》一章的String
對象章節(jié))。如果要完成字符串相關(guān)操作,就必須判斷字符是否落在0xD800
到0xDFFF
這個區(qū)間。
下面是能夠正確處理字符串遍歷的函數(shù)。
function getSymbols(string) {
var length = string.length;
var index = -1;
var output = [];
var character;
var charCode;
while (++index < length) {
character = string.charAt(index);
charCode = character.charCodeAt(0);
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
output.push(character + string.charAt(++index));
} else {
output.push(character);
}
}
return output;
}
var symbols = getSymbols('????');
symbols.forEach(function(symbol) {
// ...
});
替換(String.prototype.replace
)、截取子字符串(String.prototype.substring
, String.prototype.slice
)等其他字符串操作,都必須做類似的處理。
Base64是一種編碼方法,可以將任意字符轉(zhuǎn)成可打印字符。使用這種編碼方法,主要不是為了加密,而是為了不出現(xiàn)特殊字符,簡化程序的處理。
JavaScript原生提供兩個Base64相關(guān)方法。
var string = 'Hello World!';
btoa(string) // "SGVsbG8gV29ybGQh"
atob('SGVsbG8gV29ybGQh') // "Hello World!"
這兩個方法不適合非ASCII碼的字符,會報錯。
btoa('你好')
// Uncaught DOMException: The string to be encoded contains characters outside of the Latin1 range.
要將非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') // "你好"
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: