[TOC] ## 概述 ### 定义 字符串就是若干个排在一起的字符,放在单引号或双引号之中。 ~~~ 'abc' "abc" ~~~ 单引号字符串的内部,可以使用双引号;双引号字符串的内部,可以使用单引号。 ~~~ 'key="value"' "It's a long journey" ~~~ 如果要在单引号字符串的内部,使用单引号(或者在双引号字符串的内部,使用双引号),就必须在内部的单引号(或者双引号)前面加上反斜杠,用来转义。 ~~~ 'Did she say \'Hello\'?' "Did she say \"Hello\"?" ~~~ 字符串默认只能写在一行内,分成多行将会报错。 ~~~ 'a b c' // SyntaxError: Unexpected token ILLEGAL ~~~ 上面代码将一个字符串分成三行,JavaScript就会报错。 如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠。 ~~~ var longString = "Long \ long \ long \ string"; longString // "Long long long string" ~~~ 上面代码表示,加了反斜杠以后,原来写在一行的字符串,可以分成多行,效果与写在同一行完全一样。 但是,这种写法有两个注意点,首先,它是ECMAScript 5新添加的,老式浏览器(如IE 8)不支持,其次,反斜杠的后面必须是换行符,而不能有其他字符(比如空格),否则会报错。 连接运算符(+)可以连接多个单行字符串,用来模拟多行字符串。 ~~~ var longString = "Long " + "long " + "long " + "string"; ~~~ 另外,有一种利用多行注释,生成多行字符串的变通方法。 ~~~ (function () { /* line 1 line 2 line 3 */}).toString().split('\n').slice(1,-1).join('\n') // "line 1 // line 2 // line 3" ~~~ ### 转义 反斜杠在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符。 需要用反斜杠转义的特殊字符,主要有下面这些: * \0 代表没有内容的字符(\u0000) * \b 后退键(\u0008) * \f 换页符(\u000C) * \n 换行符(\u000A) * \r 回车键(\u000D) * \t 制表符(\u0009) * \v 垂直制表符(\u000B) * \' 单引号(\u0027) * \" 双引号(\u0022) * \\ 反斜杠(\u005C) * \XXX 用三位八进制数(0到377)代表一些特殊符号,比如\251表示版权符号。 * \xXX 用两位十六进制数(00到FF)代表一些特殊符号,比如\xA9表示版权符号。 * \uXXXX 用四位十六进制的Unicode编号代表某个字符,比如\u00A9表示版权符号。 下面是最后三种字符的特殊写法的例子。 ~~~ "\251" // "©" "\xA9" // "©" "\u00A9" // "©" ~~~ 如果非特殊字符前面使用反斜杠,则反斜杠会被省略。 ~~~ "\a" // "a" ~~~ 上面代码表示a是一个正常字符,前面加反斜杠没有特殊含义,则反斜杠会被自动省略。 如果字符串的正常内容之中,需要包含反斜杠,则反斜杠前需要再加一个反斜杠,用来对自身转义。 ~~~ "Prev \\ Next" // "Prev \ Next" ~~~ ### 字符串与数组 字符串可以被视为字符数组,因此可以使用数组的方括号运算符,用来返回某个位置的字符(从0开始)。 ~~~ var s = 'hello'; s[0] // "h" s[1] // "e" s[4] // "o" // 也可以直接对字符串使用方括号运算符 'hello'[1] // "e" ~~~ 如果方括号中的数字超过字符串的范围,或者方括号中根本不是数字,则返回undefined。 ~~~ 'abc'[3] // undefined 'abc'[-1] // undefined 'abc'["x"] // undefined ~~~ 但是,字符串与数组的相似性仅此而已。实际上,字符串是类似数组的对象,且无法改变字符串之中的单个字符。 ~~~ var s = 'hello'; delete s[0]; s // "hello" s[1] = 'a'; s // "hello" s[5] = '!'; s // "hello" ~~~ 上面代码表示,字符串内部的单个字符无法改变和增删,这些操作会默默地失败。 length属性返回字符串的长度,该属性也是无法改变的。 ~~~ var s = 'hello'; s.length // 5 s.length = 3; s.length // 5 s.length = 7; s.length // 5 ~~~ 上面代码表示字符串的length属性无法改变,但是不会报错。 字符串也无法添加新属性。 ~~~ var s = "Hello World"; s.x = 123; s.x // undefined ~~~ 上面代码为字符串s添加了一个x属性,结果无效,总是返回undefined。 上面这些行为的原因是,在JavaScript内部,变量s其实指向字符串“Hello World”的地址,而“Hello World”本身是一个常量,所以无法改变它,既不能新增,也不能删除。另一方面,当一个字符串被调用属性时,它会自动转为String对象的实例(参见《标准库》一章),调用结束后,该对象自动销毁。这意味着,下一次调用字符串的属性时,实际是调用一个临时生成的新对象,而不是上一次调用时生成的那个对象,所以取不到赋值在上一个对象的属性。如果想要为字符串添加属性,只有在它的原型对象String.prototype上定义(参见《面向对象编程》一章)。 ## 字符集 JavaScript使用Unicode字符集,也就是说在JavaScript内部,所有字符都用Unicode表示。ECMAScript 3要求使用Unicode 2.1或以上版本,ECMAScript 5则要求使用Unicode 3及以上版本。 不仅JavaScript内部使用Unicode储存字符,而且还可以直接在程序中使用Unicode,所有字符都可以写成"\uxxxx"的形式,其中xxxx代表该字符的Unicode编码。比如,\u00A9代表版权符号。 ~~~ var s = '\u00A9'; s // "©" ~~~ 每个字符在JavaScript内部都是以16位(即2个字节)的UTF-16格式储存。也就是说,JavaScript的单位字符长度固定为2个字节。 但是需要注意的是,UTF-16有两种长度:对于U+0000到U+FFFF之间的字符,长度为16位(即2个字节);对于U+10000到U+10FFFF之间的字符,长度为32位(即4个字节),而且前两个字节在0xD800到0xDBFF之间,后两个字节在0xDC00到0xDFFF之间。举例来说,U+1D306对应的字符为