♒️ 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,要算上特殊字符
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
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);
}
2
3
4
注意
JavaScript 中的字符串不能更改其中的一个字符:
let str = 'Hi';
str[0] = 'h'; // error
console.log( str[0] ); // 无法运行
2
3
4
只能重新创建一个字符串(修改的部分加上不修改的部分),分配给以前的字符串:
let str = 'Hi';
str = 'h' + str[1];
console.log( str );
2
3
# 更多关于字符串的方法
# 更改字符串的大小写(整个字符串)
toLowerCase() (opens new window) 和 toUpperCase() (opens new window)
console.log('Interface'.toUpperCase()) // INTERFACE
console.log('Interface'.toUpperCase()) // interface
2
只修改其中一个字符:
console.log('Interface'[0].toUpperCase()) // Interface
console.log('Interface'[0].toLowerCase()) // interface
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
的判断条件,因为有可能第一个字符就是结果,而0
在if
中判断为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
2str.startsWith(str)
/str.endsWith(str)
分别是从字符串的开头或者结尾开始搜索:console.log( "Widget".startsWith("Wid") ); // true console.log( "Widget".endsWith("get") ); // false
1
2
# 获取子字符串
JavaScript 中有三种获取字符串的方法: substring
、 substr
和 slice
。
str.slice(start [, end])
(end
是可选参数):返回字符串从start
到end
的位置: 【注意不包括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
2start
/end
可以为负数,从字符串结尾计算:let str = "stringify"; console.log(str.slice(-4, -1)) // 'gif'
1
2str.substring()
允许start
大于end
(但是不支持负数的参数),其他几乎与slice
相同:let str = "stringify"; console.log( str.substring(2, 6) ); // "ring" console.log( str.substring(6, 2) ); // "ring"
1
2
3str.substr(start [, length])
从start
开始取length
长度的字符串:let str = "stringify"; console.log( str.substr(2, 4) );
1
2start
可以为负值, 从字符串结尾计算:let str = "stringify"; console.log( str.substr(-4, 2) ); // 'gi'
1
2
总结:
方法 选择方式…… 负值参数 slice(start, end)
从 start
到end
(不含end
)允许 substring(start, end)
start
与end
之间(包括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
2String.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大写字母一般顺序在小写字母之后。
通过字符代码比较字符串的顺序,越大的代码意味着字符越大。
- 所有小写字母追随在大写字母之后,因为它们的代码更大。
- 一些像
Ö
的字母与主要字母表不同。这里,它的代码比任何从a
到z
的代码都要大。
利用 str.localeCompare(str2)
完成「符合语言正确」的字符串比较。会根据语言规则返回一个整数,这个整数能指示字符串 str
在排序顺序中排在字符串 str2
前面、后面、还是相同:
- 如果
str
排在str2
前面,则返回负数。 - 如果
str
排在str2
后面,则返回正数。 - 如果它们在相同位置,则返回
0
。
根据不同的语言的字母都不相同。
# 字符串总结
定义字符串有三种方式。
- 使用反引号允许跨越多行,并且可以插入表达式。
JavaScript 中的字符串使用的是 UTF-16 编码。
介绍了许多处理字符串的方法:
- 获取字符时,使用
[]
。 - 获取字符串的长度,使用
str.length
- 获取子字符串,使用
slice()
。 - 字符串的大 / 小写转换,使用:
toLowerCase()
/toUpperCase()
。 - 查找子字符串时,使用
indexOf
或includes/startsWith/endsWith
进行简单检查。 - 比较字符串一般按照字符代码比较。
- 获取字符时,使用
更多的字符串方法:手册 (opens new window)