字符串是 不可变的 JavaScript 字符序列。每个字符都是一个 16 位 UTF-16 代码单元。这意味着一个 Unicode 字符由一个或两个 JavaScript 字符表示。每当您计算字符数或拆分字符串时,您主要需要注意双字符情况(请参阅第 24 章)。
单引号和双引号都可以用来 界定字符串字面量:
'He said: "Hello"'"He said: \"Hello\""'Everyone\'s a winner'"Everyone's a winner"
因此,您可以自由使用任何一种引号。但是,有一些注意事项
如果您的代码一致地使用引号,它将看起来更干净。但有时,不同的引号意味着您不必转义,这可以证明您不那么一致是合理的(例如,您通常可能使用单引号,但暂时切换到双引号来编写前面最后一个示例)。
字符串字面量中的大多数字符 只代表它们自己。反斜杠用于 转义,并启用了几种特殊功能:
您可以 通过使用反斜杠转义行尾(行终止符,行终止符)将字符串扩展到多行:
varstr='written \over \multiple \lines';console.log(str==='written over multiple lines');// true
另一种方法是使用 加号运算符进行连接:
varstr='written '+'over '+'multiple '+'lines';
\b 是退格符,\f 是换页符,\n 是换行符,\r 是回车符,\t 是水平制表符,\v 是垂直制表符。表示自身的转义字符:\' 是单引号,\" 是双引号,\\ 是反斜杠。除 b f n r t v x u 和十进制数字以外的所有字符也代表它们自己。以下是两个例子
> '\"' '"' > '\q' 'q'
\0 表示。
\xHH(HH 是两个十六进制数字) 通过 ASCII 代码指定一个字符。例如:
> '\x4D' 'M'
\uHHHH(HHHH 是四个十六进制数字) 指定一个 UTF-16 代码单元(请参阅第 24 章)。以下是两个例子
> '\u004D' 'M' > '\u03C0' 'π'
有两个操作 返回字符串的第 n 个字符。[16] 请注意,JavaScript 没有用于字符的特殊数据类型;这些操作返回字符串
> 'abc'.charAt(1) 'b' > 'abc'[1] 'b'
一些较旧的浏览器不支持通过方括号进行类似数组的字符访问。
| 值 | 结果 |
|
|
|
|
布尔值 |
|
| |
数字 | 数字作为字符串(例如, |
字符串 | 与输入相同(无需转换) |
对象 | 调用 |
| (作为函数调用,而不是作为构造函数调用) |
| |
| (不适用于 |
我更喜欢 String(),因为它更具描述性。以下是一些例子
> String(false)
'false'
> String(7.35)
'7.35'
> String({ first: 'John', last: 'Doe' })
'[object Object]'
> String([ 'a', 'b', 'c' ])
'a,b,c'请注意,对于显示数据,JSON.stringify() (JSON.stringify(value, replacer?, space?)) 通常 比规范的字符串转换效果更好:
> console.log(JSON.stringify({ first: 'John', last: 'Doe' }))
{"first":"John","last":"Doe"}
> console.log(JSON.stringify([ 'a', 'b', 'c' ]))
["a","b","c"]当然,您必须了解 JSON.stringify() 的局限性——它并不总是显示所有内容。例如,它隐藏了其值无法处理的属性(函数等等!)。从好的方面来说,它的输出可以由 eval() 解析,并且它可以将深度嵌套的数据显示为格式良好的树。
考虑到 JavaScript 自动转换的频率,转换并不总是可逆的,这很遗憾,尤其是在布尔值方面:
> String(false)
'false'
> Boolean('false')
true对于 undefined 和 null,我们也面临着类似的问题。
有两种比较字符串的方法。 首先,您可以使用比较运算符:<、>、===、<=、>=。 它们有以下缺点:
它们区分大小写
> 'B' > 'A' // ok true > 'B' > 'a' // should be true false
它们不能很好地处理变音符号和重音符号
> 'ä' < 'b' // should be true false > 'é' < 'f' // should be true false
其次,您可以使用 String.prototype.localeCompare(other),它往往表现更好,但并不总是受支持的(有关详细信息,请参阅搜索和比较)。以下是 Firefox 控制台中的交互
> 'B'.localeCompare('A')
2
> 'B'.localeCompare('a')
2
> 'ä'.localeCompare('b')
-2
> 'é'.localeCompare('f')
-2小于零的结果意味着接收者“小于”参数。大于零的结果意味着接收者“大于”参数。
只要其操作数之一是字符串,运算符 + 就会执行字符串连接。 如果您想在变量中收集字符串片段,则复合赋值运算符 += 很有用:
> var str = ''; > str += 'Say hello '; > str += 7; > str += ' times fast!'; > str 'Say hello 7 times fast!'
看起来每当将一个片段添加到 str 时,前面的方法都会创建一个新的字符串。较旧的 JavaScript 引擎就是这样做的,这意味着您可以通过首先将所有片段收集在一个数组中,然后在最后一步将它们连接起来,从而提高字符串连接的性能:
> var arr = [];
> arr.push('Say hello ');
> arr.push(7);
> arr.push(' times fast');
> arr.join('')
'Say hello 7 times fast'但是,较新的引擎通过 + 优化字符串连接,并在内部使用类似的方法。 因此,加号运算符在这些引擎上速度更快。
前一种调用方式比较常见。
String.fromCharCode(codeUnit1, codeUnit2, ...) 生成一个字符串,其字符是由 16 位无符号整数 codeUnit1、codeUnit2 等指定的 UTF-16 代码单元。 例如:
> String.fromCharCode(97, 98, 99) 'abc'
如果要将数字数组转换为字符串,可以通过 apply() 来实现(请参阅 func.apply(thisValue, argArray))
> String.fromCharCode.apply(null, [97, 98, 99]) 'abc'
原始字符串的所有方法都存储在 String.prototype 中(请参阅原始值从包装器借用其方法)。接下来,我将描述它们如何处理原始字符串,而不是 String 的实例。
以下方法从接收器中提取子字符串
String.prototype.charAt(pos)
返回一个字符串,其中包含位置 pos 处的字符。 例如:
> 'abc'.charAt(1) 'b'
以下两个表达式返回相同的结果,但一些较旧的 JavaScript 引擎仅支持 charAt() 来访问字符
str.charAt(n)str[n]
String.prototype.charCodeAt(pos)
返回位置 pos 处的 JavaScript 字符(UTF-16 代码单元;请参阅 第 24 章)的代码(16 位无符号整数)。
> 'abc'.split('').map(function (x) { return x.charCodeAt(0) })
[ 97, 98, 99 ]charCodeAt() 的反函数是 String.fromCharCode()。
String.prototype.slice(start, end?)
返回从位置 start 开始到位置 end(不包括)的子字符串。 这两个参数都可以是负数,然后将字符串的 length 添加到它们中:
> 'abc'.slice(2) 'c' > 'abc'.slice(1, 2) 'b' > 'abc'.slice(-2) 'bc'
String.prototype.substring(start, end?)
slice(),它类似,但可以处理负数位置,并且在不同浏览器中的实现更加一致。String.prototype.split(separator?, limit?)
提取由 separator 分隔的接收器的子字符串,并将它们返回到一个数组中。该方法有两个参数:
separator:字符串或正则表达式。如果缺少,则返回完整的字符串,并包装在一个数组中。limit:如果给出,则返回的数组最多包含 limit 个元素。以下是一些例子
> 'a, b,c, d'.split(',') // string
[ 'a', ' b', 'c', ' d' ]
> 'a, b,c, d'.split(/,/) // simple regular expression
[ 'a', ' b', 'c', ' d' ]
> 'a, b,c, d'.split(/, */) // more complex regular expression
[ 'a', 'b', 'c', 'd' ]
> 'a, b,c, d'.split(/, */, 2) // setting a limit
[ 'a', 'b' ]
> 'test'.split() // no separator provided
[ 'test' ]如果有一个组,则匹配项也会作为数组元素返回
> 'a, b , '.split(/(,)/) [ 'a', ',', ' b ', ',', ' ' ] > 'a, b , '.split(/ *(,) */) [ 'a', ',', 'b', ',', '' ]
使用 ''(空字符串)作为分隔符来生成一个包含字符串字符的数组
> 'abc'.split('')
[ 'a', 'b', 'c' ]上一节是关于提取子字符串,而本节是关于将给定的字符串转换为新的字符串。 这些方法的典型用法如下:
varstr=str.trim();
换句话说,原始字符串在被(非破坏性地)转换后就被丢弃
String.prototype.trim()
> '\r\nabc \t'.trim() 'abc'
String.prototype.concat(str1?, str2?, ...)
> 'hello'.concat(' ', 'world', '!')
'hello world!'String.prototype.toLowerCase()
> 'MJÖLNIR'.toLowerCase() 'mjölnir'
String.prototype.toLocaleLowerCase()
toLowerCase() 的工作方式相同,但遵循当前语言环境的规则。根据 ECMAScript 规范:“只有在少数情况下(例如土耳其语),该语言的规则与常规 Unicode 大小写映射冲突时,才会存在差异。”String.prototype.toUpperCase()
> 'mjölnir'.toUpperCase() 'MJÖLNIR'
String.prototype.toLocaleUpperCase()
toUpperCase() 的工作方式相同,但遵循当前语言环境的规则。String.prototype.indexOf(searchString, position?)
从 position(默认为 0)开始搜索 searchString。它返回找到 searchString 的位置,如果找不到则返回 -1
> 'aXaX'.indexOf('X')
1
> 'aXaX'.indexOf('X', 2)
3请注意,在字符串中查找文本时,正则表达式同样有效。例如,以下两个表达式是等效的:
str.indexOf('abc')>=0/abc/.test(str)
String.prototype.lastIndexOf(searchString, position?)
从 position(默认为结尾)开始向后搜索 searchString。它返回找到 searchString 的位置,如果找不到则返回 -1:
> 'aXaX'.lastIndexOf('X')
3
> 'aXaX'.lastIndexOf('X', 2)
1String.prototype.localeCompare(other)
对字符串与 other 执行区分区域设置的比较。它返回一个数字:
other 之前otherother 之后例如
> 'apple'.localeCompare('banana')
-2
> 'apple'.localeCompare('apple')
0并非所有 JavaScript 引擎都能正确实现此方法。有些只是将其基于比较运算符。但是,ECMAScript 国际化 API(请参阅ECMAScript 国际化 API)确实提供了一个支持 Unicode 的实现。也就是说,如果该 API 在引擎中可用,则 localeCompare() 将起作用。
如果支持,则 localeCompare() 是比比较运算符更好的比较字符串的选择。有关更多信息,请参阅比较字符串。
以下方法使用正则表达式
String.prototype.search(regexp)(在String.prototype.search:匹配项位于哪个索引?中有更详细的说明)返回 regexp 在接收器中匹配的第一个索引(如果没有匹配项,则返回 -1):
> '-yy-xxx-y-'.search(/x+/) 4
String.prototype.match(regexp)(在String.prototype.match:捕获组或返回所有匹配的子字符串中有更详细的说明)将给定的正则表达式与接收器进行匹配。如果未设置 regexp 的标志 /g,则它将返回第一个匹配项的匹配对象:
> '-abb--aaab-'.match(/(a+)b/) [ 'ab', 'a', index: 1, input: '-abb--aaab-' ]
如果设置了标志 /g,则所有完整匹配项(组 0)都将返回到数组中
> '-abb--aaab-'.match(/(a+)b/g) [ 'ab', 'aaab' ]
String.prototype.replace(search, replacement)(在 String.prototype.replace:搜索和替换中有更详细的说明)搜索 search 并将其替换为 replacement。 search 可以是字符串或正则表达式,replacement 可以是字符串或函数。除非您使用正则表达式作为 search,并且其标志 /g 已设置,否则只会替换第一个匹配项
> 'iixxxixx'.replace('i', 'o')
'oixxxixx'
> 'iixxxixx'.replace(/i/, 'o')
'oixxxixx'
> 'iixxxixx'.replace(/i/g, 'o')
'ooxxxoxx'替换字符串中的美元符号 ($) 允许您引用完整匹配项或捕获组:
> 'iixxxixx'.replace(/i+/g, '($&)') // complete match '(ii)xxx(i)xx' > 'iixxxixx'.replace(/(i+)/g, '($1)') // group 1 '(ii)xxx(i)xx'
您还可以通过函数计算替换
> function repl(all) { return '('+all.toUpperCase()+')' }
> 'axbbyyxaa'.replace(/a+|b+/g, repl)
'(A)x(BB)yyx(AA)'