JavaScript String 类型详解:定义、特性与常用方法

作者:闭包旅人

时间:2026-10-30

浏览:368

本文深入解析JavaScript中的String类型,涵盖其作为基本数据类型与包装对象的特性。详细阐述Unicode编码机制、UTF-16存储原理及不可变性对性能的影响。系统介绍字符串的创建、转义、拼接、子串提取、位置查找、大小写转换及比较等核心API,并对比不同浏览器版本的兼容性与行为差异。

文章目录

JavaScript字符串基础与Unicode编码

JavaScript语言中并未定义独立的字符类型,所有文本数据均通过字符串(String)类型处理。在概念上,单个字符可被视为长度为1的字符串。

String既是JavaScript的基本数据类型,也对应一个包装对象。JavaScript引擎会在原始值与对象实例之间自动进行转换。下文将分别探讨字符串的原始形式及其对应的包装对象特性。

定义

字符串类型由引号包裹的一系列16位Unicode字符构成。

在表示文本数据时,字符串中的每个元素被视为一个代码点,占据序列中的一个位置。索引从0开始,依次递增,用于定位各个字符。

字符串的长度等于其所含元素的数量(即16位值的个数)。空字符串的长度为0,不包含任何字符。

Unicode编码

所有字符均可表示为'\uxxxx'格式,其中xxxx为该字符的Unicode编码值。例如,\u00A9代表版权符号©。


var s = '\u00A9';
s // "©" 

当字符串包含实际文本时,每个元素被视为独立的UTF-16代码单元。JavaScript内部以16位(2字节)的UTF-16格式存储每个字符。

UTF-16编码长度分为两种情况:U+0000至U+FFFF范围内的字符占用16位(2字节);而U+10000至U+10FFFF范围内的字符占用32位(4字节),其中前两个字节位于0xD800至0xDBFF之间,后两个字节位于0xDC00至0xDFFF之间。

以U+1D306对应的字符"𝌆"为例,其UTF-16编码为0xD834 0xDF06。虽然浏览器能正确识别这四个字节为一个完整字符,但JavaScript内部的长度属性始终固定为16位,因此会将这4字节视为两个独立的字符。


var s = '\uD834\uDF06';
s // "𝌆"
s.length // 2 

对于U+10000至U+10FFFF的4字节Unicode字符,JavaScript始终将其视为两个字符,导致length属性值为2。

字符串定义与引号使用规范

引号

字符串String可通过双引号(")或单引号(')声明。这与Java不同,Java使用双引号声明字符串,单引号声明字符。由于ECMAScript没有独立的字符类型,两种引号均可使用,但起始和结束引号必须匹配。


//正确
var sColor1 = "red";
var sColor2 = 'red';
//错误
var sColor1 = "red';
var sColor2 = 'red"; 

单引号包裹的字符串内部可以包含双引号,反之,双引号包裹的字符串内部也可以包含单引号。


'key = "value"'
"It's a long journey" 

JavaScript代码常嵌入HTML,而HTML中也常包含JavaScript。为清晰区分,建议在JavaScript和HTML代码中分别采用不同的引号风格。

在JavaScript代码中通常使用单引号表示字符串,而在HTML事件处理程序中则常使用双引号。


<button onclick = "alert('thanks')">click me</button> 

转义字符与多行字符串处理

反斜线

若需在单引号字符串中使用单引号,或在双引号字符串中使用双引号,需使用反斜线(\)进行转义。

英文缩写和所有格中的撇号与单引号字符相同,此时必须使用反斜线(\)进行转义处理。


'Wouldn\'t you prefer this book?' //"Wouldn't you prefer this book?"
'Did she say \'Hello\'?' //"Did she say 'Hello'?"
"Did she say \"Hello\"?" //"Did she say "Hello"?" 

多行字符

字符串默认必须书写在一行内,若强行分行将导致语法错误。

//报错 Uncaught SyntaxError: Invalid or unexpected token 'a b c';

在ECMAScript 3标准中,字符串必须严格书写在一行内。

ECMAScript 5允许将字符串拆分为多行,但每一行的末尾必须以反斜线(\)结束。

若希望在字符串字面量中另起一行,可使用转义字符\n。


//"onelongline"
'one\
long\
line'
/*"two
lines"*/
'two\nlines' 

转义字符

在JavaScript字符串中,反斜线(\)具有特殊含义。反斜线后接特定字符时,不再表示其字面含义,而是表示特殊字符,这类字符称为转义字符。

\0 空字节 \n 换行 \t 制表 \b 空格 \r 回车 \f 进纸 \\ 斜杠 \' 单引号 \" 双引号 \xnn 以十六进制nn表示一个字符(n为0-f),如\x41表示'A' \unnnn 以十六进制nnnn表示一个Unicode字符(n为0-f),如\u03a3表示希腊字符ε

在非特殊字符前使用反斜杠,该反斜杠会被忽略。

'\a' // "a"

若字符串中需要包含反斜杠本身,则需在反斜线前再加一个反斜线,以对其自身进行转义。

"Prev \\ Next" // "Prev \ Next"

字符串不可变性与性能影响

特点

JavaScript中的字符串是不可变的。一旦字符串创建,便无法修改其内容。若要改变变量保存的字符串,必须先销毁原字符串,再用包含新值的字符串重新赋值。

可通过+运算符连接其他字符串来创建新字符串。


var lang = "java";
lang = lang + "script"; //'javascript' 

上述代码的实际执行过程为:首先创建一个能容纳10个字符的新字符串,填充'java'和'script',最后销毁原有的'java'和'script'字符串,因为它们已不再被引用。

该过程在后台自动发生,这也是旧版本浏览器(如IE6)中字符串拼接效率较低的原因,但后续浏览器版本已优化此问题。

字符串转换方法

转字符串

将值转换为字符串主要有两种方法:toString()和String()。

[注意]可以使用空字符串"" + 某个值,将该值转换为字符串。

toString()

第一种方法是使用几乎所有值都具备的toString()方法,该方法返回相应值的字符串表现形式。

[注意]undefined和null没有toString()方法。


undefined.toString();//错误
null.toString();//错误
true.toString();//'true'
false.toString();//'false'
'abc'.toString();//'abc'
1.23.toString();//'1.23'
({}).toString();//[object Object]
[1,2,3,4].toString();//'1,2,3,4'
(new Date()).toString();//"Sun Jun 05 2016 10:04:53 GMT+0800 (中国标准时间)"
/ab/i.toString();//'/ab/i'

String()

当不确定要转换的值是否为undefined或null时,可使用转型函数String()。

转型函数String()遵循以下规则:

【1】如果值是null,返回'null';如果值是undefined,返回'undefined'。

【2】如果值不是null或undefined,则调用其toString()方法并返回原始类型值。

【3】若toString()方法返回的是对象,则继续调用valueOf()方法返回原始类型值;若valueOf()返回的仍是对象,则会报错。


// "3"
String({toString: function () {
return 3;
}
})
// "[object Object]"
String({valueOf: function () {
return 2;
}
})
// "3"
String({
valueOf: function () {
return 2;
},
toString: function () {
return 3;
}
})

字符串长度与通用方法

长度属性

每个String类型实例都拥有length属性,表示字符串中的字符个数。由于字符串不可变,其长度也是固定的。

字符串的length属性不会在for/in循环中被枚举,也无法通过delete操作符删除。

[注意]对于字符串s,最后一个字符的索引为s.length - 1。


var str = "test";
console.log(str.length);//4
str.length = 6;
console.log(str,str.length);//"test",4 

实例方法

对象通用方法

String类型作为字符串的包装类型,继承了Object对象的三个通用方法:toString()、toLocaleString()和valueOf()。

【toString()】

toString()方法返回string的原始字符串值。

【toLocaleString()】

toLocaleString()方法返回string的原始字符串值。

【valueOf()】

valueOf()方法返回string的原始字符串值。


console.log("test".valueOf());//"test"
console.log("test".toString());//"test"
console.log("test".toLocaleString());//"test" 

字符访问与提取方法

访问字符方法

字符串访问字符的方法共有四种:charAt()、中括号[]、charCodeAt()和fromCharCode()。

【chartAt()】

charAt()方法接收一个基于0的字符位置参数,返回指定位置的字符。若参数为空或NaN,默认参数为0;若参数超出范围,则返回空字符串。


var str = "hello";
console.log(str.charAt(1));//e
console.log(str.charAt(-1));//''
console.log(str.charAt(10));//''
console.log(str.charAt());//h console.log(str.charAt(NaN));//h

charAt()方法涉及Number()函数的隐式类型转换:若转换为数值,按上述规则输出;若转换为NaN,则输出第0个字符。


var str = "hello";
console.log(str.charAt(true));//'e'
console.log(str.charAt(false));//'h'
console.log(str.charAt('abc'));//'h'
console.log(str.charAt({}));//'h'
console.log(str.charAt([2]));//'l'

[注意]x.charAt(pos)与x.substring(pos, pos+1)、x.substr(pos,1)、x.slice(pos,pos+1)的结果相等。


var str = "hello";
console.log(str.charAt(1));//'e'
console.log(str.substring(1,2));//'e'
console.log(str.slice(1,2));//'e'
console.log(str.substr(1,1));//'e' 

【中括号】

ECMAScript 5定义了另一种访问字符的方法,使用方括号加数字索引访问特定字符。若参数超出范围或为NaN,输出undefined;无参数时报错。该方法不涉及Number()转型函数的隐式类型转换,但单数值数组参数可转换为数值。

[注意]IE7及以下浏览器不支持此语法。


var str = "hello";
console.log(str[0]);//h
console.log(str[[1]]);//e
console.log(str[false]);//undefined
console.log(str[-1]);//undefined
console.log(str[NaN]);//undefined
console.log(str[]);//报错

【charCodeAt()】

charCodeAt()方法类似于charAt(),接收基于0的字符位置参数,但返回指定位置字符的16位Unicode编码值。返回值是0至65535(即0x0000-0xffff)之间的整数。

若参数为空或NaN,默认参数为0;若参数超出范围,则返回NaN。


var str = "hello";
console.log(str.charCodeAt());//104
console.log(str.charCodeAt(0));//104
console.log(str.charCodeAt(1));//101
console.log(str.charCodeAt(-1));//NaN
console.log(str.charCodeAt(10));//NaN
console.log(str.charCodeAt(NaN));//104

同样地,charCodeAt()方法涉及Number()函数的隐式类型转换:若转换为数值,按上述规则输出;若转换为NaN,则输出第0个字符的字符编码。


var str = "hello";
console.log(str.charCodeAt(true));//101
console.log(str.charCodeAt(false));//104
console.log(str.charCodeAt('abc'));//104
console.log(str.charCodeAt({}));//104
console.log(str.charCodeAt([2]));//l08

【fromCharCode()】

String构造函数拥有一个静态方法fromCharCode(),用于接收一个或多个字符编码并将其转换为字符串。从本质上看,该方法与实例方法charCodeAt()执行相反操作。若参数为空或NaN,返回空字符串;若参数超出0-65535范围,输出字符不可控。


console.log(String.fromCharCode(104,101,108,108,111));//'hello'
console.log(String.fromCharCode(0x6211,0x662f,0x5c0f,0x706b,0x67f4));//'我是小火柴'
console.log(String.fromCharCode());//''
console.log(String.fromCharCode(NaN));//''
console.log(String.fromCharCode(-1));
console.log(String.fromCharCode(65560));

若一个字符占用四字节,需拆分为两个字符表示。


console.log(String.fromCharCode(0xD842, 0xDFB7)); // "𠮷" 

字符串拼接与子串提取

字符串拼接

字符串拼接主要有concat()方法和加号(+)运算符两种。

【concat()】

concat()方法用于将一个或多个字符串拼接起来,返回新字符串,原字符串不变。若参数(除第一个外)非字符串,则通过String()方法隐式转换为字符串后再拼接。


var stringValue = 'hello ';
var result = stringValue.concat('world','!');
console.log(result);//'hello world!'
console.log(stringValue);//'hello' 

[注意]第一个参数必须是字符串,若为其他类型(数组除外)则报错。

(1).concat('2');//报错 (true).concat('false');//报错 ({}).concat('abc');//报错

[注意]由于数组也存在concat()方法,参数转换方式取决于首先出现的参数是数组还是字符串。

'1,2,3,'.concat([4,5]);//'1,2,3,4,5' [1,2,3].concat(',4,5');//[1, 2, 3, ",4,5"]

【加号运算符(+)】

虽然concat()是专门用于拼接字符串的方法,但实践中更常用加号运算符(+),因其往往比concat()更简单易行。


var stringValue = 'hello ';
console.log(stringValue.concat('world','!'));//'hello world!'
console.log(stringValue + 'world' + '!');//'hello world!' 

[注意]仅当操作数中至少有一个是字符串,或对象转换为字符串时,才执行字符串拼接。


1 + 2;//3
'1' + 2;//'12'
var o = {valueOf:function(){return '1';}};
o + 2;//'12'
var o = {valueOf:function(){return 1;}};
o + 2;//3

创建子字符串

创建子字符串的方法包括slice()、substr()和substring()。

【slice()】

slice(start,end)方法接收start和end两个参数,返回从start位置到end位置(不包含end)的子字符串;若end为undefined或省略,则返回从start到字符串末尾的所有字符。

若start为负数,则start = max(length + start, 0)。

若end为负数,则end = max(length + end, 0)。

start和end参数不可交换位置。


var stringValue = 'hello world';
console.log(stringValue.slice());//'hello world'
console.log(stringValue.slice(2));//'llo world'
console.log(stringValue.slice(2,undefined));//'llo world'
console.log(stringValue.slice(2,-5));//'llo '
console.log(stringValue.slice(2,-20));//''
console.log(stringValue.slice(20));//''
console.log(stringValue.slice(-2,2));//''
console.log(stringValue.slice(-2,-20));//'' 
console.log(stringValue.slice(-2,20));//'ld'
console.log(stringValue.slice(-20,2));//'he'
console.log(stringValue.slice(-20,-2));//'hello wor'

slice()方法涉及Number()转型函数的隐式类型转换:当start转换为NaN时,相当于start = 0;当end转换为NaN(end为undefined除外)时,输出空字符串。


var stringValue = 'hello world';
console.log(stringValue.slice(NaN));//'hello world'
console.log(stringValue.slice(0,NaN));//''
console.log(stringValue.slice(true,[3]));//'el'
console.log(stringValue.slice(null,undefined));//'hello world'
console.log(stringValue.slice({}));//'hello world'
console.log(stringValue.slice('2',[5]));//'llo'

【substring()】

substring(start,end)方法接收start和end两个参数,返回从start位置到end位置(不包含end)的子字符串;若end为undefined或省略,则返回从start到字符串末尾的所有字符。

若任一参数为NaN或负数,则被0取代。

若任一参数大于字符串长度,则被字符串长度取代。

若start大于end,则交换两者的值。


var stringValue = 'hello world';
console.log(stringValue.substring());//'hello world'
console.log(stringValue.substring(2));//'llo world'
console.log(stringValue.substring(2,undefined));//'llo world'
console.log(stringValue.substring(20));//''
console.log(stringValue.substring(-2,2));//'he'
console.log(stringValue.substring(NaN,2));//'he'
console.log(stringValue.substring(-2,20));//'hello world'
console.log(stringValue.substring(3,2));//'l'
console.log(stringValue.substring(3,NaN));//'hel'
console.log(stringValue.substring(-20,2));//'he'
console.log(stringValue.substring(-20,-2));//''

同样地,substring()方法也涉及Number()转型函数的隐式类型转换。


var stringValue = 'hello world';
console.log(stringValue.substring(true,[3]));//'el'
console.log(stringValue.substring(null,undefined));//'hello world'
console.log(stringValue.substring({}));//'hello world'
console.log(stringValue.substring('2',[5]));//'llo' 

【substr()】

substr(start,end)方法接收start和end两个参数,end代表返回子字符串的字符个数;该方法返回从start位置开始的end个字符组成的子字符串;若end为undefined或省略,则返回从start到字符串末尾的所有字符。

若start为负数,则start = max(length + start, 0)。

若start为NaN,则相当于start = 0。

若end为负数或NaN,则end = 0,因此会返回空字符串。

start和end参数不可交换位置。

[注意]该方法非ECMAScript标准,已被弃用。

[注意]IE8及以下浏览器在处理向substr()传递负值的情况时存在问题,会返回原始字符串。


var stringValue = 'hello world';
console.log(stringValue.substr());//'hello world'
console.log(stringValue.substr(2));//'llo world'
console.log(stringValue.substr(2,undefined));//'llo world'
console.log(stringValue.substr(2,NaN));//''
console.log(stringValue.substr(NaN,2));//'he'
console.log(stringValue.substr(20));//''
console.log(stringValue.substr(-2,3));//'ld'
console.log(stringValue.substr(-2,20));//'ld'
console.log(stringValue.substr(-20,2));//'he'
console.log(stringValue.substr(-20,-2));//'' 
console.log(stringValue.substr(2,5));//llo w

同样地,substr()方法也涉及Number()转型函数的隐式类型转换。


var stringValue = 'hello world';
console.log(stringValue.substr(true,[3]));//'el'
console.log(stringValue.substr(null,undefined));//'hello world'
console.log(stringValue.substr({}));//'hello world'
console.log(stringValue.substr('2',[5]));//'llo w' 

字符串位置查找

字符串位置

查找子字符串位置的方法有两个:indexOf()和lastIndexOf()。

【indexOf()】

indexOf(searchString,start)方法接收searchString和start两个参数,返回searchString首次出现的位置,若未找到则返回-1。

该方法隐式调用String()转型函数,将searchString非字符串值转换为字符串;隐式调用Number()转型函数,将start非数字值(undefined除外)转换为数值。

searchString表示要搜索的子字符串;start表示搜索开始位置,若忽略该参数或为undefined、NaN或负数时,start = 0。


var string = 'hello world world';
console.log(string.indexOf('ld'));//9
console.log(string.indexOf('ld',undefined));//9
console.log(string.indexOf('ld',NaN));//9
console.log(string.indexOf('ld',-1));//9
console.log(string.indexOf('ld',10));//15
console.log(string.indexOf('ld',[10]));//15
console.log(string.indexOf('true',[10]));//-1
console.log(string.indexOf(false,[10]));//-1

【lastIndexOf()】

lastIndexOf(searchString,start)方法接收searchString和start两个参数,返回searchString最后一次出现的位置,若未找到则返回-1。

同样地,该方法隐式调用String()转型函数,将searchString非字符串值转换为字符串;隐式调用Number()转型函数,将start非数字值(undefined除外)转换为数值。

searchString表示要搜索的子字符串;start表示搜索开始位置,若忽略该参数或为undefined、NaN时,start = length - 1。

[注意]与indexOf()不同,若start为负数,该方法返回-1。


var string = 'hello world world';
console.log(string.indexOf('ld'));//9
console.log(string.indexOf('ld',undefined));//9
console.log(string.indexOf('ld',NaN));//9
console.log(string.indexOf('ld',-1));//-1
console.log(string.indexOf('ld',10));//15
console.log(string.indexOf('ld',[10]));//15
console.log(string.indexOf('true',[10]));//-1
console.log(string.indexOf(false,[10]));//-1

【tips】查找出字符串所有符合条件的子字符串

可通过循环调用indexOf()或lastIndexOf()来找到所有匹配的子字符串。


function allIndexOf(str,value){
var result = [];
var pos = str.indexOf(value);
while(pos > -1){
result.push(pos);
pos = str.indexOf(value,pos+value.length);
}
return result;
}
console.log(allIndexOf('helllhelllhelll','ll'));//[2,7,12]

空白字符处理与trim方法

【trim()】

ECMAScript 5为所有字符串定义了trim()方法。该方法创建字符串副本,删除前置及后缀的所有空白字符,然后返回结果。

由于trim()返回的是字符串副本,原始字符串中的前置及后缀空格保持不变。

[注意]IE8及以下浏览器不支持此方法。


var string = ' hello world ';
console.log(string.trim());//'hello world'
console.log(string);//' hello world ' 

空白字符不仅包括空格,还包括制表符(\t)、换行符(\n)和回车符(\r)。

'\r\nabc \t'.trim() // 'abc'

此外,Firefox、Safari和WebKit还支持非标准的trimRight()用于删除字符串结尾的空白字符。


var string = ' hello world ';
console.log(string.trimRight());//' hello world'; 

【tips】用trim()来判断输入的字符是否为空


if(usename.trim().length){
alert('correct');
}else{
alert('error');
} 

【tips】用正则表达式模拟trim()


function fnTrim(str){
return str.replace(/^\s+|\s+$/,'')
} 
console.log(fnTrim(' hello world '));//'hello world' 

大小写转换与字符串比较

大小写转换

ECMAScript中涉及字符串大小写转换的方法有4个:toLowerCase()、toLocaleLowerCase()、toUpperCase()、toLocaleUpperCase()。

toLowerCase()和toUpperCase()是经典方法,借鉴自java.lang.String。toLocaleLowerCase()和toLocaleUpperCase()则是针对特定地区的实现。对于某些地区,地区专用方法与通用方法结果相同,但少数语言(如土耳其语)需应用特殊Unicode规则,此时必须使用地区专用方法以确保正确转换。

【toUpperCase()】

toUpperCase()方法将字符串转换为大写。

【toLowerCase()】

toLowerCase()方法将字符串转换为小写。

【toLocaleUpperCase()】

toLocaleUpperCase()方法将字符串转换为大写(针对地区)。

【toLocaleLowerCase()】

toLocaleLowerCase()方法将字符串转换为小写(针对地区)。

[注意]在不确定代码运行语言环境的情况下,使用地区专用方法更为稳妥。


var string = 'Hello World';
console.log(string.toLowerCase());//hello world
console.log(string.toLocaleLowerCase());//hello world
console.log(string.toUpperCase());//HELLO WORLD
console.log(string.toLocaleUpperCase());//HELLO WORLD

这4种方法均不支持String()隐式类型转换,仅支持字符串类型。

(true).toLowerCase();//报错 (2).toLocaleLowerCase();//报错 ({}).toUpperCase();//报错 ([]).toLocaleUpperCase();//报错

[注意]大小写转换方法可以连续使用。


var string = 'Hello World';
console.log((string.toUpperCase()).toLowerCase());//hello world 

【localeCompare()】

localeCompare()方法用于比较两个字符串,遵循以下规则:

【1】若字符串在字母表中应排在字符串参数之前,则返回负数(通常为-1)。

【2】若字符串等于字符串参数,则返回0。

【3】若字符串在字母表中应排在字符串参数之后,则返回正数(通常为1)。


var stringValue = 'yellow';
console.log(stringValue.localeCompare('brick'));//1 'y'> 'b'
console.log(stringValue.localeCompare('yellow'));//0 'yellow' == 'yellow'
console.log(stringValue.localeCompare('zoo'));//-1 'yellow' < 'zoo'

[注意]虽然字母表中大写字母通常排在小写字母之前(即大写字母 < 小写字母),但localeCompare()方法会考虑自然语言排序情况,将'B'排在'a'之前。


console.log('B'.localeCompare('a'));//1
console.log('B' > 'a');//false
console.log('b'.localeCompare('a'));//1
console.log('b' > 'a');//true

以上所述是小编给大家介绍的Javascript类型系统之String字符串类型详解的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对本站网站的支持!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章