目录

♒️ JavaScript 字符串

在 JavaScript 中,文本数据被以字符串形式存储,单个字符没有单独的类型。字符串的内部格式始终是 UTF-16 (opens new window),它不依赖于页面编码。

# 声明字符串

字符串可以被包含在单引号 ‘’“”`` 反引号。

  • 反引号的特殊使用,可以通过 ${…} 将任何表达式嵌入到字符串中:

    function sum(a, b) {
      return a + b;
    }
    
    console.log(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
    
    1
    2
    3
    4
    5

    并且反引号允许字符串跨行:

    let guestList = `Guests:
     * John
     * Pete
     * Mary
    `;
    
    1
    2
    3
    4
    5

    ⚠️ 单引号或者双引号不能跨行,只能添加换行的转义符 \n

  • 较少的用法,在反引号之前指定一个「模版函数」,函数 func 被自动调用,接收字符串和嵌入式表达式,并处理它们。此功能可以将字符串包装到自定义模版或其他函数中。

# 特殊字符

在字符串中允许使用一些特殊的字符使用于不同的场景:

字符 描述
\n 换行
\' , \" 在字符串中添加引号
\\ 在字符串中添加反斜线
\t 制表符
\b , \f , \v 退格,换页,垂直标签 —— 为了兼容性,现在已经不使用了。
\xXX 具有给定十六进制 Unicode XX 的 Unicode 字符,例如: '\x7A''z' 相同。
\uXXXX 以 UTF-16 编码的十六进制代码 XXXX 的 Unicode 字符,例如 \u00A9 是版权符号 © 的 Unicode。它必须正好是 4 个十六进制数字。(字符串使用 emoji 的用法)
\u{X…XXXXXX} (1 到 6 个十六进制字符) 具有给定 UTF-32 编码的 Unicode 符号。一些罕见的字符用两个 Unicode 符号编码,占用 4 个字节。通过它插入长代码。

# 访问字符串

# 获取字符串的长度

字符串有属性 length 表示字符串长度:

console.log('abc'.length) // 3

cosole.log('abc//'.length) // 4,要算上特殊字符
1
2
3

注意

length 是属性不是函数,读取不需要加括号。

读取 pos 位置的一个字符,有两种方法:

  • 直接使用 [pos] 方括号读取;
  • 使用 str.charAt[pos]

🌰 例子:

let str = `Hello`;

// 第一个字符
alert( str[0] ); // H
alert( str.charAt(0) ); // H

// 最后一个字符
alert( str[str.length - 1] ); // o
1
2
3
4
5
6
7
8

方括号是获取字符的一种现代化方法,而 charAt 是历史原因才存在的。它们之间的唯一区别是,如果没有找到字符, [] 返回 undefined ,而 charAt 返回一个空字符串:

let str = `Hello`;

alert( str[1000] ); // undefined
alert( str.charAt(1000) ); // ''(空字符串)
1
2
3
4

使用 for ... of 遍历字符串:

for (let char of "Hello") {
  alert(char); 
}

1
2
3
4

注意

JavaScript 中的字符串不能更改其中的一个字符:

let str = 'Hi';

str[0] = 'h'; // error
console.log( str[0] ); // 无法运行
1
2
3
4

只能重新创建一个字符串(修改的部分加上不修改的部分),分配给以前的字符串:

let str = 'Hi';
str = 'h' + str[1];
console.log( str );
1
2
3

# 更多关于字符串的方法

# 更改字符串的大小写(整个字符串)

toLowerCase() (opens new window)toUpperCase() (opens new window)

console.log('Interface'.toUpperCase()) // INTERFACE
console.log('Interface'.toUpperCase()) // interface
1
2

只修改其中一个字符:

console.log('Interface'[0].toUpperCase()) // Interface
console.log('Interface'[0].toLowerCase()) // interface
1
2

# 查找子字符串的方法

  • str.indexOf(substr, pos) (opens new window) :从给定的位置 pos 开始,在 str 中查找 substr ,如果没有找到,则返回 -1否则返回匹配成功的位置

    let str = 'Widget with id';
    
    console.log(str.indexOf('Widget')); // 0 一开始就找到
    console.log(str.indexOf('widget')); // -1,没有找到,检索是大小写敏感的
    
    console.log(str.indexOf("id")); // 1,"id" 在位置 1 处(……idget 和 id) 不完全匹配所以可以指定检索位置
    console.log(str.indexOf('id', 2)) // 12 跳过第一个"id"
    
    1
    2
    3
    4
    5
    6
    7

    可以循环遍历查找,保存所有找到的位置:

    let str = 'As sly as a fox, as strong as an ox';
    
    let target = 'as';
    let pos = 0;
    let res = []
    while (true) {
      let foundPos = str.indexOf(target, pos);
      if (foundPos == -1) break;
    
      console.log( `Found at ${foundPos}` );
      res.push(foundPos)
      pos = foundPos + 1; // 继续从下一个位置查找
    }
    
    console.log(res) // [7, 17, 27]
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    ⚠️ 位置包括空格字符。

    简写方法:

    while((pos = str.indexOf(target, pos + 1)) != -1){
      res.push(pos)
    }
    
    1
    2
    3

    对于 str.lastIndexOf(substr, pos) 方法,查找结果是相反的(从字符串的结尾开始查找)。

    不要使用查找结果为 if 的判断条件,因为有可能第一个字符就是结果,而 0if 中判断为 false 。应该检查是否等于 -1

    let str = "Widget with id";
    
    if (str.indexOf("Widget") != -1) {
        alert("We found it");
    }
    
    1
    2
    3
    4
    5
  • ⭐️ 现代方法 str.includes(substr, pos)

    只需要检验是否匹配,可以不带位置 pos

    console.log("Widget with id".includes("Widget")) // true
    
    1

    可选参数 pos 是开始搜索的位置:

    console.log("Midget".includes("id")); // true
    console.log("Midget".includes("id", 3)); // false
    
    1
    2

    str.startsWith(str) / str.endsWith(str) 分别是从字符串的开头或者结尾开始搜索:

    console.log( "Widget".startsWith("Wid") ); // true 
    console.log( "Widget".endsWith("get") ); // false
    
    1
    2

# 获取子字符串

JavaScript 中有三种获取字符串的方法: substringsubstrslice

  • str.slice(start [, end])end 是可选参数):返回字符串从 startend 的位置: 【注意不包括 end 处的字符】

    let str = "stringify";
    console.log(str.slice(0, 5)) // 'strin'
    console.log(str.slice(0, 1)) // 's'
    
    1
    2
    3

    如果没有 end 参数,则一直从 start 位置运行到字符串末尾:

    let str = "stringify";
    console.log(str.slice(2)); // 'ringify'
    
    1
    2

    start / end 可以为负数,从字符串结尾计算:

    let str = "stringify";
    console.log(str.slice(-4, -1)) // 'gif'
    
    1
    2
  • str.substring() 允许 start 大于 end (但是不支持负数的参数),其他几乎与 slice 相同:

    let str = "stringify";
    console.log( str.substring(2, 6) ); // "ring"
    console.log( str.substring(6, 2) ); // "ring"
    
    1
    2
    3
  • str.substr(start [, length])start 开始取 length 长度的字符串:

    let str = "stringify";
    console.log( str.substr(2, 4) );
    
    1
    2

    start 可以为负值, 从字符串结尾计算:

    let str = "stringify";
    console.log( str.substr(-4, 2) ); // 'gi'
    
    1
    2

总结:

方法 选择方式…… 负值参数
slice(start, end) startend (不含 end 允许
substring(start, end) startend 之间(包括 start ,但不包括 end 不允许负值
substr(start, length) start 开始获取长为 length 的字符串 允许 start 为负数

提示

相较于其他两个变体, slice 稍微灵活一些,它允许以负值作为参数并且写法更简短。

# 字符串的比较

JavaScript 中,字符串按字母顺序逐字比较。比较顺序按照个字符都有对应的数字代码( UTF-16 (opens new window) 编码)。有特殊的方法可以获取代码表示的字符,以及字符对应的代码。

  • str.codePointAt(pos) :返回 pos 位置的字符代码:

    console.log("z".codePointAt(0)) // 122
    console.log("Z".codePointAt(0)) // 90
    
    1
    2
  • String.fromCodePoint(code) :通过字符代码创建字符:

    console.log(String.fromCodePoint(90)) // 'Z'、
    
    1
  • 使用十六进制代码(二进制的字符代码转换为十六进制),添加 Unicode 字符串:

    console.log('\u005a') // 'Z' (90 -> 5a)
    
    1

遍历输出代码为 65..220 的字符:

let str = '';

for (let i = 65; i <= 220; i++) {
  str += String.fromCodePoint(i);
}
console.log( str );
// ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„
// ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜ
1
2
3
4
5
6
7
8

大写字母一般顺序在小写字母之后

通过字符代码比较字符串的顺序,越大的代码意味着字符越大。

  • 所有小写字母追随在大写字母之后,因为它们的代码更大。
  • 一些像 Ö 的字母与主要字母表不同。这里,它的代码比任何从 az 的代码都要大。

利用 str.localeCompare(str2) 完成「符合语言正确」的字符串比较。会根据语言规则返回一个整数,这个整数能指示字符串 str 在排序顺序中排在字符串 str2 前面、后面、还是相同:

  • 如果 str 排在 str2 前面,则返回负数。
  • 如果 str 排在 str2 后面,则返回正数。
  • 如果它们在相同位置,则返回 0

根据不同的语言的字母都不相同。

# 字符串总结

  • 定义字符串有三种方式。

    • 使用反引号允许跨越多行,并且可以插入表达式。
  • JavaScript 中的字符串使用的是 UTF-16 编码。

  • 介绍了许多处理字符串的方法:

    • 获取字符时,使用 []
    • 获取字符串的长度,使用 str.length
    • 获取子字符串,使用 slice()
    • 字符串的大 / 小写转换,使用: toLowerCase() / toUpperCase()
    • 查找子字符串时,使用 indexOfincludes/startsWith/endsWith 进行简单检查。
    • 比较字符串一般按照字符代码比较。

更多的字符串方法:手册 (opens new window)

📢 上次更新: 2022/09/02, 10:18:16