文字格式化

本章介紹如何在 JavaScript 中使用字串和文字。

字串

JavaScript 的 字串 型別用於表示文字資料。它是一組 16 位無符號整數 (UTF-16 程式碼單元) 的“元素”。字串中的每個元素都在字串中佔據一個位置。第一個元素位於索引 0,下一個位於索引 1,依此類推。字串的長度是字串中元素的數量。您可以使用字串字面量或字串物件建立字串。

字串字面量

您可以使用單引號或雙引號建立簡單的字串

js
'foo'
"bar"

可以使用轉義序列建立更高階的字串

十六進位制轉義序列

\x 之後的數字被解釋為 十六進位制 數字。

js
"\xA9" // "©"

Unicode 轉義序列

Unicode 轉義序列要求 \u 後至少有四個十六進位制數字。

js
"\u00A9" // "©"

Unicode 程式碼點轉義

使用 Unicode 程式碼點轉義,任何字元都可以使用十六進位制數字轉義,以便可以使用高達 0x10FFFF 的 Unicode 程式碼點。使用簡單的 Unicode 轉義,通常需要分別寫入代理對的一半才能獲得相同的結果。

另請參見 String.fromCodePoint()String.prototype.codePointAt()

js
"\u{2F804}"

// the same with simple Unicode escapes
"\uD87E\uDC04"

字串物件

String 物件是字串原始資料型別的包裝器。

js
const foo = new String("foo"); // Creates a String object
console.log(foo); // [String: 'foo']
typeof foo; // 'object'

您可以對字串字面量值呼叫 String 物件的任何方法 - JavaScript 會自動將字串字面量轉換為臨時 String 物件,呼叫該方法,然後丟棄臨時 String 物件。您還可以使用字串字面量的 length 屬性。

除非您明確需要使用 String 物件,否則您應該使用字串字面量,因為 String 物件可能具有反直覺的行為。例如

js
const firstString = "2 + 2"; // Creates a string literal value
const secondString = new String("2 + 2"); // Creates a String object
eval(firstString); // Returns the number 4
eval(secondString); // Returns a String object containing "2 + 2"

String 物件有一個屬性 length,它指示字串中的 UTF-16 程式碼單元數量。例如,以下程式碼將 helloLength 賦值為 13,因為 "Hello, World!" 有 13 個字元,每個字元都由一個 UTF-16 程式碼單元表示。您可以使用陣列括號樣式訪問每個程式碼單元。您不能更改單個字元,因為字串是不可變的類陣列物件

js
const hello = "Hello, World!";
const helloLength = hello.length;
hello[0] = "L"; // This has no effect, because strings are immutable
hello[0]; // This returns "H"

Unicode 標量值大於 U+FFFF(例如一些罕見的中文/日文/韓文/越南語字元和一些表情符號)的字元在 UTF-16 中使用兩個代理程式碼單元儲存。例如,包含單個字元 U+1F600 "Emoji grinning face" 的字串將具有長度 2。使用方括號訪問此類字串中的單個程式碼單元可能會產生不希望有的結果,例如形成包含不匹配的代理程式碼單元的字串,違反了 Unicode 標準。(示例應在修復 MDN 錯誤 857438 後新增到此頁面。)另請參見 String.fromCodePoint()String.prototype.codePointAt()

String 物件具有多種方法:例如,那些返回字串本身變體的方法,例如 substringtoUpperCase

下表總結了 String 物件的方法。

String 的方法

方法 描述
charAt(), charCodeAt(), codePointAt() 返回字串中指定位置的字元或字元程式碼。
indexOf(), lastIndexOf() 分別返回字串中指定子字串的位置或指定子字串的最後一個位置。
startsWith(), endsWith(), includes() 返回字串是否以指定字串開頭、結尾或包含指定字串。
concat() 組合兩個字串的文字並返回一個新字串。
split() 透過將字串分割為子字串,將 String 物件分割成字串陣列。
slice() 提取字串的一部分並返回一個新字串。
substring(), substr() 返回字串的指定子集,可以透過指定開始和結束索引或開始索引和長度來實現。
match(), matchAll(), replace(), replaceAll(), search() 使用正則表示式。
toLowerCase(), toUpperCase()

分別返回字串的所有小寫或所有大寫。

normalize() 返回呼叫字串值的 Unicode 規範化形式。
repeat() 返回一個字串,該字串由物件的元素重複給定次陣列成。
trim() 從字串的開頭和結尾修剪空格。

多行模板字面量

模板字面量 是字串字面量,允許嵌入表示式。您可以使用多行字串和字串插值功能。

模板字面量用反引號 (`) 字元而不是雙引號或單引號括起來。模板字面量可以包含佔位符。這些由美元符號和花括號 (${expression}) 表示。

多行

原始碼中插入的任何換行符都是模板字面量的一部分。使用普通字串,您需要使用以下語法才能獲得多行字串

js
console.log(
  "string text line 1\n\
string text line 2",
);
// "string text line 1
// string text line 2"

要使用多行字串獲得相同的效果,您現在可以編寫

js
console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"

嵌入表示式

為了在普通字串中嵌入表示式,您將使用以下語法

js
const five = 5;
const ten = 10;
console.log(
  "Fifteen is " + (five + ten) + " and not " + (2 * five + ten) + ".",
);
// "Fifteen is 15 and not 20."

現在,使用模板字面量,您可以利用語法糖,使這種替換更易讀

js
const five = 5;
const ten = 10;
console.log(`Fifteen is ${five + ten} and not ${2 * five + ten}.`);
// "Fifteen is 15 and not 20."

有關更多資訊,請閱讀 模板字面量 的內容,位於 JavaScript 參考 中。

國際化

Intl 物件是 ECMAScript 國際化 API 的名稱空間,它提供語言敏感的字串比較、數字格式化以及日期和時間格式化功能。Intl.CollatorIntl.NumberFormatIntl.DateTimeFormat 物件的建構函式是 Intl 物件的屬性。

日期和時間格式化

Intl.DateTimeFormat 物件可用於格式化日期和時間。以下程式碼示例將日期格式化為美國英語格式。(結果在其他時區可能不同。)

js
// July 17, 2014 00:00:00 UTC:
const july172014 = new Date("2014-07-17");

const options = {
  year: "2-digit",
  month: "2-digit",
  day: "2-digit",
  hour: "2-digit",
  minute: "2-digit",
  timeZoneName: "short",
};
const americanDateTime = new Intl.DateTimeFormat("en-US", options).format;

// Local timezone vary depending on your settings
// In CEST, logs: 07/17/14, 02:00 AM GMT+2
// In PDT, logs: 07/16/14, 05:00 PM GMT-7
console.log(americanDateTime(july172014));

數字格式化

Intl.NumberFormat 物件可用於格式化數字,例如貨幣。

js
const gasPrice = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
  minimumFractionDigits: 3,
});

console.log(gasPrice.format(5.259)); // $5.259

const hanDecimalRMBInChina = new Intl.NumberFormat("zh-CN-u-nu-hanidec", {
  style: "currency",
  currency: "CNY",
});

console.log(hanDecimalRMBInChina.format(1314.25)); // ¥ 一,三一四.二五

排序

Intl.Collator 物件可用於比較和排序字串。

例如,德語實際上有兩種不同的排序順序,即電話簿排序和字典排序。電話簿排序強調發音,就像在排序之前將“ä”、“ö”等擴充套件為“ae”、“oe”等一樣。

js
const names = ["Hochberg", "Hönigswald", "Holzman"];

const germanPhonebook = new Intl.Collator("de-DE-u-co-phonebk");

// as if sorting ["Hochberg", "Hoenigswald", "Holzman"]:
console.log(names.sort(germanPhonebook.compare).join(", "));
// "Hochberg, Hönigswald, Holzman"

一些德語單詞在詞尾新增變音符號,因此在字典中,忽略變音符號進行排序是合理的(除非排序的單詞由變音符號區分:schonschön 之前)。

js
const germanDictionary = new Intl.Collator("de-DE-u-co-dict");

// as if sorting ["Hochberg", "Honigswald", "Holzman"]:
console.log(names.sort(germanDictionary.compare).join(", "));
// "Hochberg, Holzman, Hönigswald"

有關 Intl API 的更多資訊,請參閱 Introducing the JavaScript Internationalization API