【相關推薦:javascript影片教學、web前端】
不論在何種程式語言中,字串都是重要的資料類型,跟著我了解更多JavaScript
字串知識吧!
字串就是由字元組成的字串,如果學過C
、 Java
就應該知道,字元本身也可以獨立成為一個型別。但是, JavaScript
沒有單一的字元類型,只有長度為1
的字串。
JavaScript
的字串採用固定的UTF-16
編碼,不論我們寫程式時採用何種編碼,都不會影響。
字串有三種寫法:單引號、雙引號、反引號。
let single = 'abcdefg';//單引號let double = "asdfghj";//雙引號let backti = `zxcvbnm`;//反引號
單、雙引號具有相同的地位,我們不做區分。
字串格式化
反引號允許我們使用${...}
優雅的格式化字串,取代使用字串加運算。
let str = `I'm ${Math.round(18.5)} years old.`;console.log(str);
程式碼執行結果:
多行字串
反引號還可以允許字串跨行,當我們編寫多行字串的時候非常有用。
let ques = `Is the author handsome? A. Very handsome; B. So handsome; C. Super handsome;`;console.log(ques);
程式碼執行結果:
是不是看起來覺得也沒有什麼?但使用單雙引號是不能實現的,如果想要得到同樣的結果可以這麼寫:
let ques = 'Is the author handsome?nA. Very handsome;nB. So handsome;nC. Super handsome;'; console.log(ques);
以上程式碼包含了一個特殊字元n
,它是我們程式設計過程中最常見的特殊字元了。
字元n
又名"換行符",支援單雙引號輸出多行字串。當引擎輸出字串時,若遇到n
,就會另換一行繼續輸出,從而實現多行字串。
雖然n
看起來是兩個字符,但只佔用一個字符位置,這是因為在字串中是轉義符,被轉義符修飾的字符就變成了特殊字符。
特殊字元清單
特殊字元 | 描述 |
---|---|
n | 換行符,用於新起一行輸出文字。 |
r | 回車符,將遊標移到行首,在Windows 系統中使用rn 表示一個換行,意思是遊標需要先到行首,然後再到下一行才可以換一個新的行。其他系統直接使用n 就可以了。 |
' " | 單雙引號,主要是因為單雙引號是特殊字符,我們想在字符串中使用單雙字符就要轉義。 |
\ | 反斜杠,同樣因為 是特殊字符,如果我們只是想 |
xXX | Unicode x7A XX |
| |
f b v | |
u00A9 Unicode XXXX | uXXXX |
u{X...X} 1-6 | |
z z Unicode 為7A )。 |
為
X...X
的 | UTF-32 X...X Unicode |
"");// "console.log("\n is new line character.");// nconsole.log('u00A9')// ©console.log('u{1F60D} ');//
程式碼執行結果:
有了轉義符的存在,理論上我們可以輸出任何字符,只要找到它對應的編碼就可以了。
避免使用'
、 "
對於字串中的單雙引號,我們可以透過在單引號中使用雙引號、在雙引號中使用單引號,或直接在反引號中使用單雙引號,就可以巧妙的避免使用轉義符,例如:
console.log("I'm a student."); //雙引號使用單引號console.log('"" is used.'); //單引號使用雙引號console.log(`' " is used.`); //在反引號中使用單雙引號
程式碼執行結果如下:
透過字串的.length
屬性,我們可以得到字串的長度:
console.log("HelloWorldn".length);//11
這裡n
只佔用了一個字元。
《基礎類型的方法》章節我們探討了
JavaScript
中的基礎型別為什麼會有屬性和方法,你還記得嗎?
字串是字元組成的字串,我們可以透過[字符下标]
存取單一的字符,字元下標從0
開始:
let str = "The author is handsome."; console.log(str[0]);//Tconsole.log(str[4]);//aconsole.log(str[str.length-1]);//.程式碼
執行結果:
我們也可以使用charAt(post)
函式來取得字元:
let str = "The author is handsome.";console.log(str.charAt(0)); //Tconsole.log(str.charAt(4)); //aconsole.log(str.charAt(str.length-1));//.
二者執行效果完全相同,唯一的差異在於越界存取字元時:
let str = "01234";console.log(str[ 9]);//undefinedconsole.log(str.charAt(9));//""(空字串)
我們也可以使用for ..of
遍歷字串:
for(let c of '01234'){ console.log(c);}
JavaScript
中的字串一經定義就不可更改,舉個例子:
let str = "Const";str[0] = 'c' ;console.log(str);
程式碼執行結果:
如果想要取得一個不一樣的字串,只能新建:
let str = "Const";str = str.replace('C','c');console.log(str);
看起來我們似乎改變了字符串,實際上原來的字串並沒有被改變,我們得到的是replace
方法回傳的新字串。
轉換字串大小寫,或轉換字串中單一字元的大小寫。
這兩個字串的方法比較簡單,舉例帶過:
console.log('Good Boy'.toLowerCase());//good boyconsole.log('Good Boy'.toUpperCase());//GOOD BOYconsole.log('Good Boy'[5].toLowerCase());//b
程式碼執行結果:
.indexOf(substr,idx)
函數從字串的idx
位置開始,找出子字串substr
的位置,成功傳回子字串首字元下標,失敗回傳-1
。
let str = "google google";console.log(str.indexOf('google')); //0 idx預設為0console.log(str.indexOf('google',1)); //7 從第二個字元開始找出console.log(str.indexOf('xxx')); //-1 沒找到回傳-1
程式碼執行結果:
如果我們想要查詢字串中所有子字串位置,可以使用迴圈:
let str = "I love love love love u.";let sub = "love";let pos = -1;while((pos = str.indexOf (sub,pos+1)) != -1) console.log(pos);
程式碼執行結果如下:
.lastIndexOf(substr,idx)
倒著查詢子字串,先找最後一個符合的字串:
let str = "google google";console.log(str.lastIndexOf('google'));//7 idx預設為0
由於indexOf()
和lastIndexOf()
方法在查詢不成功的時候會返回-1
,而~-1 === 0
。也就是說只有在查詢結果不為-1
的情況下使用~
才為真,所以我們可以:
let str = "google google";if(~indexOf('google',str)){ ...}
通常情況下,我們不建議在無法明顯體現語法特性的地方使用一個語法,這會在可讀性上產生影響。還好以上程式碼只出現在舊版的程式碼中,這裡提到就是為了大家在閱讀舊程式碼的時候不會產生困惑。
補充:
~
是按位取反運算符,例如:十進制的數字2
的二進位形式為0010
,~2
的二進位形式就是1101
(補碼),也就是-3
。簡單的理解方式,
~n
等價於-(n+1)
,例如:~2 === -(2+1) === -3
.includes(substr,idx)
用來判斷substr
是否在字串中, idx
是查詢開始的位置
console.log('Google Google'.includes('Google'));//trueconsole.log('Google Google'. includes('xxxxxx'));//falseconsole.log('9966'.includes('99',1));//false
程式碼執行結果:
.startsWith('substr')
和.endsWith('substr')
分別判斷字串是否以substr
開始或結束
console.log("google".startsWith('go'));//trueconsole.log('google' .endsWith('le'));//trueconsole.log('google'.endsWith('ie'));//false
程式碼執行結果:
.substr()
、 .substring()
、 .slice()
皆用於取字串的子字串,不過用法各有不同。
.substr(start,len)
傳回字串從start
開始len
個字元組成的字串,如果省略len
,就截取到原字串的末尾。 start
可以為負數,表示從後往前第start
個字元。
let str = "0123456789";console.log(str.substr(1))//123456789,從1開始到最後console.log(str.substr(3,2))//34,從3開始的2個字元console.log(str.substr(-3,2))//78,倒數第二個開始
程式碼執行結果:
.slice(start,end)
傳回字串從start
開始到end
結束(不包含)的字串。 start
和end
可以為負數,表示倒數第start/end
個字元。
let str = '0123456789';console.log(str.slice(1,5));//1234,區間[1,5)之間的字元console.log(str.slice(1));//123456789 ,從1到結尾console.log(str.slice(-4,-1));//678,倒數第四個到倒數第1個
程式碼執行結果:
.substring(start,end)
作用幾乎和.slice()
相同,差異在兩個地方:
end > start
;0
;舉例:
let str = '0123456789';console.log(str .substring(1,3));//12console.log(str.substring(3,1));//12console.log(str.substring(-1,3));//012,-1被當作0
程式碼執行結果:
比較三者的差異:
方法 | 描述 | 參數 |
---|---|---|
.slice(start,end) | [start,end) | 可負 |
.substring(start,end) | [start,end) | 負值為0 |
.substr(start,len) | 從start 開始長為len 的子字串 | 可負 |
方法多了自然就選擇困難了,這裡建議記住
.slice()
就可以了,相比於其他兩種更靈活。
我們在前文已經提及字串的比較,字串依照字典序進行排序,每個字元背後都是編碼, ASCII
編碼就是一個重要的參考。
例如:
console.log('a'>'Z');//true
字元之間的比較,本質上是代表字元的編碼之間的比較。 JavaScript
使用UTF-16
編碼字串,每個字元都是16
為的程式碼,想要知道比較的本質,就需要使用.codePointAt(idx)
取得字元的編碼:
console.log('a'.codePointAt( 0));//97console.log('Z'.codePointAt(0));//90
程式碼執行結果:
使用String.fromCodePoint(code)
可以把編碼轉為字元:
console.log(String.fromCodePoint(97));console.log(String.fromCodePoint(90));
程式碼執行結果如下:
這個過程可以用轉義符u
實現,如下:
console.log('u005a');//Z,005a是90的16進位寫法console.log('u0061');//a,0061是97的16進位寫法
下面我們探討編碼為[65,220]
區間的字元:
let str = '';for(let i = 65; i<=220; i++){ str+=String.fromCodePoint(i);}console.log(str);
程式碼執行部分結果如下:
上圖並沒有顯示所有的結果,快去試試看。
基於國際化標準ECMA-402
, JavaScript
已經實現了一個特殊的方法( .localeCompare()
)比較各種字符串,採用str1.localeCompare(str2)
的方式:
str1 < str2
,返回負數;str1 > str2
,回傳正數;str1 == str2
,回傳0;舉個例子:
console.log("abc".localeCompare('def'));//-1
為什麼不直接用比較運算子呢?
這是因為英文字元有一些特殊的寫法,例如, á
是a
的變體:
console.log('á' < 'z');//false
雖然也是a
,但是比z
還要大! !
此時需要使用.localeCompare()
方法:
console.log('á'.localeCompare('z'));//-1
str.trim()
去除字串前後空白字符, str.trimStart()
, str.trimEnd()
刪除開頭、結尾的空格;
let str = " 999 ";console.log(str.trim());//999
str.repeat(n)
重複n
次字串;
let str = ' 6';console.log(str.repeat(3));//666
str.replace(substr,newstr)
取代第一個子字串, str.replaceAll()
用於取代所有子字串;
let str = '9 +9';console.log(str.replace('9','6'));//6+9console.log(str.replaceAll('9','6'));//6+6
還有很多其他方法,我們可以訪問手冊以獲取更多知識。
JavaScript
使用UTF-16
編碼字串,也就是使用兩個位元組( 16
位元)表示一個字符,但是16
位元資料只能表示65536
個字符,對於常見字符自然不在話下,但是對於生僻字(中文的)、 emoji
、罕見數學符號等就力不從心了。
這種時候就需要擴展,使用更長的位數( 32
位元)表示特殊字符,例如:
console.log(''.length);//2console.log('?'.length);//2
代碼執行結果:
這麼做的結果是,我們無法使用常規的方法來處理它們,如果我們單一輸出其中的每個位元組,會發生什麼事?
console.log(''[0]);console.log(''[1]);
程式碼執行結果:
可以看到,單一輸出位元組是不能辨識的。
還好String.fromCodePoint()
和.codePointAt()
兩個方法是可以處理這種情況的,這是因為二者是最近才加入的。在舊版的JavaScript
中,只能使用String.fromCharCode()
和.charCodeAt()
兩個方法轉換編碼和字符,但是他們不適用於特殊字符的情況。
我們可以透過判斷一個字符的編碼範圍,判斷它是否是一個特殊字符,從而處理特殊字符。如果一個字元的程式碼在0xd800~0xdbff
之間,那麼他是32
位元字元的第一部分,它的第二部分應該在0xdc00~0xdfff
。
舉個例子:
console.log(''.charCodeAt(0).toString(16));//d83 dconsole.log('?'.charCodeAt(1).toString(16));//de02
程式碼執行結果:
在英文中,存在著許多基於字母的變體,例如:字母a
可以是àáâäãåā
的基本字符。這些變體符號並沒有全部儲存在UTF-16
編碼中,因為變化組合太多了。
為了支援所有的變體組合,同樣使用多個Unicode
字符表示單一變體字符,在編程過程中,我們可以使用基本字符加上“裝飾符號”的方式表達特殊字符:
console.log('au0307 ');//ȧ console.log('au0308');//ȧ console.log('au0309');//覓 console.log('Eu0307');//Ė console.log('Eu0308');//Ë console.log('Eu0309');//Ẻ
程式碼執行結果:
一個基礎字母還可以有多個裝飾,例如:
console.log('Eu0307u0323');//Ẹ̇ console.log('Eu0323u0307');//Ẹ̇
程式碼執行結果:
這裡有一個問題,在多個裝飾的情況下,裝飾的排序不同,實際上展示的字元是一樣的。
如果我們直接比較這兩種表示形式,卻會得到錯誤的結果:
let e1 = 'Eu0307u0323'; let e2 = 'Eu0323u0307'; console.log(`${e1}==${e2} is ${e1 == e2}`)
程式碼執行結果:
為了解決這種情況,有一個** Unicode
規範化演算法,可以將字串轉為通用**格式,由str.normalize()
實作:
let e1 = 'Eu0307u0323';
let e2 = 'Eu0323u0307';
console.log(`${e1}==${e2} is ${e1.normalize() == e2.normalize()}`)
程式碼執行結果:
【相關推薦:javascript影片教學、web前端】
以上就是JavaScript字串常見基礎方法精講的詳細內容,更多請關注php中文網其它相關文章!