字符串(string)是一组由 16 位值组成的不可变的有序序列,每个字符通常来自于 Unicode 字符集。JavaScript 通过字符串类型来表示文本。字符串的长度(length)是其所含 16 位值的个数。JavaScript 字符串(和其数组)的索引从零开始:第一个字符的位置是 0,第二个字符的位置是 1,以此类推。空字符串(empty string)长度为 0,JavaScript 中并没有表示单个字符的“字符型”。要表示一个 16 位值,只需将其赋值给字符串变量即可,这个字符串长度为 1 。
| var hzh = ""; |
| console.log("空字符串的长度:"); |
| console.log(hzh.length); |
| [Running] node "e:\HMV\JavaScript\JavaScript.js" |
| 空字符串的长度: |
| 0 |
| |
| [Done] exited with code=0 in 0.3 seconds |
字符集,内码和JavaScript字符串
JavaScript 采用 UTF-16 编码的 Unicode 字符集,JavaScript 字符串是由一组无符号的16位值组成的序列。最常用的 Unicode 字符(这些字符属于“基本多语种平面”)都是通过 16 位的内码表示,并代表字符串中的单个字符,那些不能表示为 16 位的 Unicode 字符则遵循 UTF-16 编码规则————用两个 16位值组成的一个序列(亦称做“代理项对”)表示。这意味着一个长度为 2 的 JavaScript 字符串(两个 16 位值)有可能表示一个 Unicode 字符:
| var p = "π"; |
| var e = "e"; |
| p.length |
| e.length |
| var hzh1 = "π"; |
| var hzh2 = "e"; |
| console.log("hzh1的长度:"); |
| console.log(hzh1.length); |
| console.log("hzh2的长度:"); |
| console.log(hzh2.length); |
| [Running] node "e:\HMV\JavaScript\JavaScript.js" |
| hzh1的长度: |
| 1 |
| hzh2的长度: |
| 1 |
| |
| [Done] exited with code=0 in 0.175 seconds |
JavaScript 定义的各式字符串操作方法均作用于 16 位值,而非字符,且不会对代理项对做单独处理,同样 JavaScript 不会对字符串做标准化的加工,甚至不能保证字符串是合法的 UTF-16 格式。
注
“基本多语种平面”(Basic Multilingual Plane,BMP),也称“零断面”(Plan 0),是 Unicode 中的一个编码区段。编码介于 U+0000~U+FFFF 之间。
3.2.1 字符串直接量
在 JavaScript 程序中的字符串直接量,是由单引号或双引号括起来的字符序列。由单引号定界的字符串中可以包含双引号,由双引号定界的字符串中也可以包含单引号。这里有几个字符串直接量的例子:
| "" |
| 'testing' |
| "3.14" |
| 'name="myform"' |
| "Wouldn't you prefer O'Reilly's book?" |
| "This string\nhas two lines" |
| "π is the ratio of a circle's circumference to its diameter" |
在 ECMAScript 3 中,字符串直接量必须写在一行中,而在 ECMAScript 5 中,字符串直接量可以拆分成数行,每行必须以反斜线(\)结束,反斜线和行结束符都不算是字符串直接量的内容。如果希望在字符串直接量中另起一行,可以使用转义字符\n :
| "two\nlines" |
| "one\ //用三行代码定义了显示为单行的字符串,只在ECMAScript 5中可用 |
| long\ |
| line" |
需要注意的是,当使用单引号来定界字符串时,需要格外小心英文中的缩写和所有格写法,比如 can't 和 O'Reilly's。因为撇号和单引号是同一个字符,所以必须使用反斜线()来转义所有的撇号。
在客户端 JavaScript 程序设计中,JavaScript 代码会夹杂 HTML 代码的字符串,HTML 代码也会夹杂 JavaScript 代码。和 JavaScript 一样,HTML 也使用单引号或者双引号来定界字符串,因此,当JavaScript 代码和 HTML 代码混杂在一起的时候,最好在 JavaScript 和 HTML 代码中各自使用独立的引号风格。例如,在 JavaScript 表达式中使用单引号表示字符串 "Thank you”,而在 HTML 事件处理程序属性中则使用双引号表示字符串:
| <button onclick="alert('Thank you')">Click Me</button> |
3.2.2 转义字符
在 JavaScript 字符串中,反斜线()有着特殊的用途,反斜线符号后加一个字符,就不再表示它们的字面含义了,比如,\n 就是一个转义字符(escape sequence),它表示的是一个换行符。
注
escape sequence 译为“转义序列”,有时也译成“转义字符”和“逃逸符”。
另一个例子是上节中提到的转义字符',表示单引号(或撇号)。当需要在一个单引号定界的字符串内使用撇号的时候,它就显得非常有用。现在你就会明白我们为什么把它们叫做转义字符了,因为反斜线可以使我们避免使用常规方式解释单引号,当单引号不是用来标记字符串结尾时,它只是一个撇号:
| 'You\'re right, it can\'t be a quote' |
下表列出了 JavaScript 中的转义字符以及它们所代表的含义。其中有两个是通用的,通过十六进制数表示 Latin-1 或 Unicode 中的任意字码。例如,\xA9 表示版权符号,版权符号的 Latin-1 编码是十六进制数 A9 。同样,\u 表示由 4 个十六进制数指定的任意 Unicode 字符,比如,\u03c0 表示字符π。
表3-1 JavaScript转义字符
转义字符 |
含义 |
\o |
NUL字符(\u0000) |
\b |
退格符(\u0008) |
\t |
水平制表符(\u0009) |
\n |
换行符(\u000A) |
\v |
垂直制表符(\u000B) |
\f |
换页符(\u000C) |
\r |
回车符(\u000D) |
\" |
双引号(\u0022) |
\' |
撇号或单引号(\uOO27) |
\\ |
反斜线(\UOO5C) |
\xXX |
由两位十六进制数XX指定的Latin-1字符 |
\uXXXX |
由4位十六进制数XXXX指定的Unicode字符 |
如果“\”字符位于没有在上表中列出的字符前,则忽略“\”(当然,JavaScript 语言将来的版本可能定义新的转义符)。比如,“#”和“#”等价。最后,上文提到过,在 ECMAScript 5 中,允许在一个多行字符串直接量里的每行结束处使用反斜线。
3.2.3 字符串的使用
JavaScript 的内置功能之一就是字符串连接。如果将加号(+)运算符用于数字,表示两数相加。但将它作用于字符串,则表示字符串连接,将第二个字符串拼接在第一个之后, 例如:
| msg = "Hello, " + "world"; |
| greeting = "Welcome to my blog," + " " + name; |
| var hzh1 = "黄子涵"; |
| var hzh2 = "是帅哥!" |
| console.log("拼接字符串:"); |
| console.log(hzh1 + hzh2); |
| [Running] node "e:\HMV\JavaScript\JavaScript.js" |
| 拼接字符串: |
| 黄子涵是帅哥! |
| |
| [Done] exited with code=0 in 0.174 seconds |
要确定一个字符串的长度————其所包含的16位值的个数————可以使用字符串的length属性。比如,要得到字符串s的长度:
除了length属性,字符串还提供许多可以调用的方法:
| var s = "hello, world" |
| s.charAt(0) |
| s.charAt(s.length-1) |
| s.substring(1,4) |
| s.slice(1,4) |
| s.slice(-3) |
| s.indexOf("l") |
| s.lastIndexOf("l") |
| s.IndexOf("1", 3) |
| s.split(", ") |
| s.replace('h', 'H') |
| s.toUpperCase() |
| var hzh = "黄子涵是帅哥!"; |
| var HZH = "hzh"; |
| console.log("输出第一个字符:"); |
| console.log(hzh.charAt(0)); |
| console.log(""); |
| console.log("输出最后一个字符:"); |
| console.log(hzh.charAt(hzh.length-1)); |
| console.log(""); |
| console.log("用substring方法输出字符串某部分:"); |
| console.log(hzh.substring(1,4)); |
| console.log(""); |
| console.log("用slice方法输出字符串某部分:"); |
| console.log(hzh.slice(1,4)); |
| console.log(""); |
| console.log("用slice方法输出字符串最后三个字符:"); |
| console.log(hzh.slice(-3)); |
| console.log(""); |
| console.log("字符“涵”首次出现的位置:"); |
| console.log(hzh.indexOf("涵")); |
| console.log(""); |
| console.log("字符“涵”最后一次出现的位置:"); |
| console.log(hzh.lastIndexOf("涵")); |
| console.log(""); |
| console.log("在位置3及之后首次出现字符“涵”的位置"); |
| console.log(hzh.indexOf("涵", 3)); |
| console.log(""); |
| console.log("将数组分割成子串:"); |
| console.log(hzh.split("是")); |
| console.log(""); |
| console.log("全文字符替换:"); |
| console.log(hzh.replace("子涵", "春钦")); |
| console.log(""); |
| console.log("转换为大写:"); |
| console.log(HZH.toUpperCase()); |
| [Running] node "e:\HMV\JavaScript\JavaScript.js" |
| 输出第一个字符: |
| 黄 |
| |
| 输出最后一个字符: |
| ! |
| |
| 用substring方法输出字符串某部分: |
| 子涵是 |
| |
| 用slice方法输出字符串某部分: |
| 子涵是 |
| |
| 用slice方法输出字符串最后三个字符: |
| 帅哥! |
| |
| 字符“涵”首次出现的位置: |
| 2 |
| |
| 字符“涵”最后一次出现的位置: |
| 2 |
| |
| 在位置3及之后首次出现字符“涵”的位置 |
| -1 |
| |
| 将数组分割成子串: |
| [ '黄子涵', '帅哥!' ] |
| |
| 全文字符替换: |
| 黄春钦是帅哥! |
| |
| 转换为大写: |
| HZH |
| |
| [Done] exited with code=0 in 0.247 seconds |
记住,在 JavaScript 中字符串是固定不变的,类似replace()toUpperCase() 的方法都返回新字符串,原字符串本身并没有发生改变。
在 ECMAScript 5中,字符串可以当做只读数组,除了使用 charAt() 方法,也可以使用方括号来访问字符串中的单个字符(16位值):
| s = "hello, world"; |
| s[0] |
| s[s.length-1] |
| var hzh = "黄子涵是帅哥!"; |
| console.log("字符串的第一个元素:"); |
| console.log(hzh[0]); |
| console.log(""); |
| console.log("字符串的最后一个元素:"); |
| console.log(hzh[hzh.length-1]); |
| [Running] node "e:\HMV\JavaScript\JavaScript.js" |
| 字符串的第一个元素: |
| 黄 |
| 字符串的最后一个元素: |
| ! |
| |
| [Done] exited with code=0 in 0.176 seconds |
基于 Mozilla 的 Web 浏览器(比如 Firefox )很久之前就支持这种方式的字符串索引,多数现代浏览器( IE 除外)也紧跟 Mozilla 的脚步,在 ECMAScript 5 成型之前就支持了这一特性。
3.2.4 模式匹配
JavaScript 定义了 RegExp() 构造函数,用来创建表示文本匹配模式的对象。这些模式称为“正则表达式”(regular expression),JavaScript 采用 Perl 中的正则表达式语法。String 和 RegExp 对象均定义了利用正则表达式进行模式匹配和査找与替换的函数。
RegExp 并不是 JavaScript 的基本类型。和 Date 一样,它只是一种具有实用 API 的特殊对象。正则表达式的语法很复杂,API 也很丰富。RgeExp 是一种强大和常用的文本处理工具。
尽管 RegExp 并不是语言中的基本数据类型,但是它们依然具有直接量写法,可以直接在 JavaScript 程序中使用。在两条斜线之间的文本构成了一个正则表达式直接量。第二条斜线之后也可以跟随一个或多个字母,用来修饰匹配模式的含义,例如:
| /^HTML/ |
| /[1-9][0-9]*/ |
| /\bjavascript\b/i |
RegExp 对象定义了很多有用的方法,字符串同样具有可以接收 RegExp 参数的方法,例如:
| var text = "testing: 1, 2, 3"; |
| var pattern = /\d+/g |
| pattern.test(text) |
| text.search(pattern) |
| text.match(pattern) |
| text.replace(pattern, "#") |
| text.split(/\D+/); |
| var hzh = "黄子涵的手机号码:1, 9, 2, 1, 3, 2, 3, 4, 9, 3"; |
| var pattern = /\d+/g; |
| console.log("看能不能匹配成功?"); |
| console.log(pattern.test(hzh)); |
| console.log(""); |
| console.log("首次匹配成功的位置:"); |
| console.log(hzh.search(pattern)); |
| console.log(""); |
| console.log("所有匹配组成的数组:"); |
| console.log(hzh.match(pattern)); |
| console.log(""); |
| console.log("把数字替换为“?”"); |
| console.log(hzh.replace(pattern,"?")); |
| console.log(""); |
| console.log("用非数字字符截取字符串:"); |
| console.log(hzh.split(/\D+/)); |
| [Running] node "e:\HMV\JavaScript\JavaScript.js" |
| 看能不能匹配成功? |
| true |
| |
| 首次匹配成功的位置: |
| 9 |
| |
| 所有匹配组成的数组: |
| [ |
| '1', '9', '2', '1', |
| '3', '2', '3', '4', |
| '9', '3' |
| ] |
| |
| 把数字替换为“?” |
| 黄子涵的手机号码:?, ?, ?, ?, ?, ?, ?, ?, ?, ? |
| |
| 用非数字字符截取字符串: |
| [ |
| '', '1', '9', '2', |
| '1', '3', '2', '3', |
| '4', '9', '3' |
| ] |
| |
| [Done] exited with code=0 in 0.176 seconds |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?