ECMAScript 6之字符串的擴展

ECMAScript 6之字符串的擴展

1. 字符的 Unicode 表示法

ES6 加強了對 Unicode 的支持,允許採用\uxxxx形式表示一個碼點在\u0000~\uFFFF之間的字符,其中xxxx表示字符的 Unicode 碼點。

'\u0061'; // 'a'
'\u0062'; // 'b'

對於Unicode碼點超過0xFFFF的數值,需要放入大括號中。

// 不放在{}中,會理解成\u20BB+8
"\u20BB8"; // "₻8"

// 放在{}中,正確解析
"\u{20BB8}"; // "𠮸" 

2. 字符串遍歷器接口

ES6 爲字符串添加了遍歷器接口,使得字符串可以被for...of循環遍歷。

for (let s of 'jidi') {
  console.log(s)
}
// "j"
// "i"
// "d"
// "i"

字符串遍歷器還可以識別大於0xFFFF的碼點。

const s = String.fromCodePoint(0x20BB8);

// 傳統for循環不能識別大於0xFFFF的碼點
for(let i = 0; i < s.length; i++) {
	console.log(s[i]);
}
// " "
// " "

// for---of循環
for(let i of s) {
	console.log(i)
}
// "𠮸"

3. 行分隔符和段分隔符

JavaScript 字符串允許直接輸入字符,以及輸入字符的轉義形式。

// 兩者等價	
'中' === '\u4e2d' // true

JavaScript 中有5個字符,只能使用轉義形式表示。

  • U+005C:反斜槓。
  • U+000D:回車。
  • U+2028:行分隔符。
  • U+2029:段分隔符。
  • U+000A:換行符。

但是JSON格式中允許直接使用行分隔符和段分隔符,如果JSON中包含行分隔符或者段分隔符,用JSON.parse解析,可能出現錯誤。爲了解決這個問題,ES2019允許JavaScript 直接輸入行分隔符和段分隔符。

// 允許直接使用行分隔符和段分隔符
let s1 = '\u2028';
let s2 = '\u2029'

4. 模板字符串

模板字符串是增強版的字符串,用反引號(`)標識。它可以當作普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量。

// 普通字符串
`模板字符串當做普通字符串使用`

// 多行字符串
`這是一個
 多行模板字符串.`

console.log(`這也是一個
 多行模板字符串`);

// 字符串中嵌入變量
let name = "jdii";
`你好,${name}, 喫早餐了嗎?`

使用模板字符串表示多行字符串,所有的空格和縮進都會被保留在輸出之中。

// 換行符和空格符都會保留
let s = 
`<ul>
  <li>first</li>
  <li>second</li>
</ul>
`

模板字符串中嵌入變量,需要將變量名寫在${}之中。

function checkUser(user) {
	if (user.name.length > 10) {
		throw new Error(`您輸入的用戶名:${user.name}長度超過了10個字符!`)
	}
}

大括號內部可以放入任意的 JavaScript 表達式,可以進行運算,引用對象屬性和調用函數。

let x = 1;
let y = 2;

// 可以是表達式,可以參與運算
`${x} + ${y} = ${x + y}`; // "1 + 2 = 3"

// 可以調用對象屬性
let person = {name: 'jidi', age: 22};
alert(`${person.name}`);

// 可以調用函數
function print() {
  return "Hello World!";
}

`${print()} -----`; // Hello World!-----

如果大括號中的值不是字符串,將按照一般的規則轉爲字符串。

let person = {name: 'jidi', age: 22};
alert(`${person}`); // [object Object]

如果模板字符串中的變量沒有聲明,將報錯。

let msg = `Hello, ${name}`; // Uncaught ReferenceError: place is not defined

5. 標籤模板

模板字符串緊跟在一個函數名後面,該函數將被調用來處理這個模板字符串。這被稱爲“標籤模板”功能。

alert`jidi`;
 
// 等價於
alert(['jidi'])

標籤模板其實是函數調用的一種特殊形式。“標籤”指的就是函數,緊跟在後面的模板字符串就是它的參數。

如果模板字符裏面有變量,會將模板字符串先處理成多個參數,再調用函數。

let x = 'jidi';
let y = 'xuxiake';

function printStr(array, ...values){
  let output = "";
  let index;
  for (index = 0; index < values.length; index++) {
    output += array[index] + values[index];
  }

  output += array[index]
  return output
}

printStr`${ x }${ y }說:早上好!`; // "jidi對xuxiake說:早上好!"

上面代碼中,函數printStr第一個參數是一個數組,數組的成員是模板字符中沒有被變量替換的部分,其它的參數都是模板字符串被變量替換後的值。

6. String.fromCodePoint()

ES5 提供的String.fromCharCode()方法不能識別碼點大於0xFFFF的字符。爲了識別大於0xFFFF的字符ES6 提供了String.fromCodePoint()方法。

// 不能識別大於0xFFFF的字符
String.fromCharCode(0x20BB8); // "ஸ"

// 可以識別大於0xFFFF的字符
String.fromCodePoint(0x20BB8); // "𠮸"

7. String.prototype.codePointAt()

JavaScript 內部,字符以 UTF-16 的格式儲存,每個字符固定爲2個字節。對於那些需要4個字節儲存的字符(Unicode 碼點大於0xFFFF的字符),JavaScript 會認爲它們是兩個字符,字符串長度會誤判爲2,charCodeAt()方法只能分別返回前兩個字節和後兩個字節的值。

ES6 提供了codePointAt()方法,能夠正確處理 4 個字節儲存的字符,返回一個字符的碼點。

let x = "𠮸";

// 長度會誤判爲2
x.length(); // 2

// charCodeAt方法會當做兩個字符處理
x.charCodeAt(0).toString(16); // "d842"
x.charCodeAt(0).toString(16); // "dfb8"

// 正確識別四字節字符
x.codePointAt().toString(16); // "20bb8"

8. String.prototype.includes(),String.prototype.startsWith(),String.prototype.endsWith()

ES6 提供了三種新方法,判斷一個字符串中是否包含子字符串。

  • includes():返回布爾值,表示是否找到了參數字符串。
  • startsWith():返回布爾值,表示參數字符串是否在原字符串的頭部。
  • endsWith():返回布爾值,表示參數字符串是否在原字符串的尾部。
let x = 'jidi';

x.startsWith('ji'); // true
x.endsWith('i'); // true
x.includes('d'); // true

上述三個方法都支持第二個參數index,表示開始搜索的位置。但是endsWith是針對前index個字符,而includesstartsWith方法針對的是從第index個位置開始到結束位置的字符。

let s = 'Hello world!';

// 針對的是第6個位置上的字符直到結束
s.startsWith('world', 6) // true
s.includes('Hello', 6) // false

// 針對的是前5個字符
s.endsWith('Hello', 5) // true

9. String.prototype.repeat()

repeat方法返回一個新字符串,表示將原字符串重複n次。

'jidi'.repeat(2); // "jidijidi"
'jidi'.repeat(0); // ""

參數如果是小數,會被取整。

'jidi'.repeat(2.5); // "jidijidi"

參數是絕對值大於等於1的負數或Infinity,報錯。

'jidi'.repeat(-1); // Uncaught RangeError: Invalid count value at String.repeat
'jidi'.repeat(Infinity); // Uncaught RangeError: Invalid count value at String.repeat

參數如果爲絕對值小於1的負數或者爲NaN,等同於參數爲0

// 參數絕對值小於1的負數等同於0
'jidi'.repeat(-0.12); // ""

// NaN等同於0
'jidi'.repeat(NaN); // ""

參數是字符串,則會先轉換成數字,然後參與運算。

'jidi'.repeat('jidi') // "jidi"轉換爲數字爲NaN,結果爲""

'jidi'.repeat('2') // "jidijidi"

10. String.prototype.padStart(),String.prototype.padEnd()

ES2017 引入了padStart()padEnd()用於字符串補全長度。如果某個字符串不夠指定長度,分別在頭部或尾部補全字符串。

// 頭部補充
'x'.padStart(5, 'jidi'); // "jidix"
'x'.padStart(4, 'jidi'); // "jidx"

// 尾部補充
'x'.padEnd(5, 'jidi'); // "xjidi"
'x'.padEnd(4, 'jidi'); // "xjid"

padStart()padEnd()一共接受兩個參數,第一個參數是字符串補全生效的最大長度n,第二個參數是用來補全的字符串s

如果原來字符串的長度,已經等於或大於最大長度,則字符串補全不生效,返回原字符串。

// 原來字符串長度已經等於或大於最大長度,方法不生效,返回原字符串
'jidi'.padStart(2, 'ab'); // 'jidi'
'jidi'.padEnd(2, 'ab'); // 'jidi'

如果用來補全的字符串與原字符串,兩者的長度之和超過了最大長度,則會截去超出位數的補全字符串。

'jidi'.padStart(10, 'this is a example'); // "this ijidi"
'jidi'.padEnd(10, 'this is a example'); // "jidithis i"

省略第二個參數,默認使用空格補全長度。

'jidi'.padStart(8); // "    jidi"
'jidi'.padEnd(8); // "jidi    "

11. String.prototype.trimStart(),String.prototype.trimEnd()

ES2019新增了trimStart()trimEnd()這兩個方法。分別用於消除首部和尾部的空格。它們返回的都是新字符串,不會修改原始字符串。

let s = "   jidi   ";

s.trim(); // "jidi"
s.trimStart(); // "jidi   "
s.trimEnd(); // "   jidi"

11. 參考鏈接

本篇博文是我自己學習筆記,原文請參考:ECMAScript 6 入門
如有問題,請及時指出!
歡迎溝通交流,郵箱:[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章