本文详细对比 JavaScript 中数组和字符串的常用方法。涵盖方括号索引访问、split与join的相互转换、concat拼接、slice截取以及indexOf和lastIndexOf查找机制。重点解析参数处理、边界条件及两者在类型转换和严格相等判断上的差异,帮助开发者更高效地处理字符串与数组操作。
前面的话
字符串和数组在 JavaScript 中拥有大量相似的方法,但二者也存在本质区别:字符串是不可变值,可视为只读数组。本文将深入对比这两类数据结构在常用方法上的异同。
可索引与转换机制
可索引
ECMAScript5 规范定义了一种通过方括号加数字索引来访问字符串特定字符的方式。
这种索引方式的最大优势在于简洁性,它替代了调用 charAt() 方法,使代码更简洁、可读性更强,且可能具备更高的执行效率。此外,字符串表现出的类数组行为使得通用的数组方法也能应用于字符串。
当提供的索引参数超出有效范围,或者为 NaN 时,访问操作将返回 undefined。
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[]);//报错
var arr = ['h','e','l','l','o'];
console.log(arr[0]);//h
console.log(arr[[1]]);//e
console.log(arr[false]);//undefined
console.log(arr[-1]);//undefined
console.log(arr[NaN]);//undefined
console.log(arr[]);//报错
转换
字符串可以通过 split() 方法转换为数组,而数组则可以通过 join() 方法还原为字符串。
【split()】
split() 方法依据指定的分隔符将字符串分割为多个子串,并将结果存储在一个数组中。分隔符可以是普通字符串,也可以是正则表达式。
该方法可选地接受第二个参数,用于限制返回数组的大小。若该参数值在 0 到 array.length 范围内,则按指定数量输出结果;否则,返回所有分割后的子串。
如果指定的分隔符在字符串中未出现,则直接返回包含原字符串的数组。
var colorText = 'red,blue,green,yellow';
console.log(colorText.split(''));//["r", "e", "d", ",", "b", "l", "u", "e", ",", "g", "r", "e", "e", "n", ",", "y", "e", "l", "l", "o", "w"]
console.log(colorText.split(','));//["red", "blue", "green", "yellow"]
console.log(colorText.split(',',2));//["red", "blue"]
console.log(colorText.split(',',6));//["red", "blue", "green", "yellow"]
console.log(colorText.split('-'));//["red,blue,green,yellow"]
console.log(colorText.split(/\,/));//["red", "blue", "green", "yellow"]
console.log(colorText.split(/e/));//["r", "d,blu", ",gr", "", "n,y", "llow"]
console.log(colorText.split(/[^\,]+/));//将除去逗号以外的字符串变为分隔符["", ",", ",", ",", ""],IE8-会识别为[",",",",","]
【join()】
join() 方法使用指定的分隔符将数组项连接成一个字符串。该方法仅接收一个参数,即用作分隔符的字符串,最终返回包含所有数组项的完整字符串。
若调用 join() 时未传入任何参数,则默认使用逗号(,)作为分隔符。
var a = [1,2,3];
console.log(a.join());//'1,2,3'
console.log(a.join(' '));//'1 2 3'
console.log(a.join(''));//'123'
var b = new Array(10);
b.join('-');//'---------',9个连字符组成的字符串
如果数组中包含 null 或 undefined 元素,join() 在生成结果字符串时会将其转换为空字符串。
var colors = [1,undefined,2,null,3];
console.log(colors.join());//'1,,2,,3'
由于字符串具有类数组对象的特性,因此也可以直接对字符串调用 join() 方法。
console.log(Array.prototype.join.call('hello', '-'));// "h-e-l-l-o"
var str = 'test';
var arr = str.split('')//["t", "e", "s", "t"]
console.log(arr.join('-'));//'t-e-s-t'
拼接与创建方法
拼接
字符串和数组共同拥有 concat() 方法,用于实现内容的拼接。
var value = 'hello';
console.log(value.concat('world'));//'helloworld'
console.log(value.concat(['world']));//'helloworld'
console.log(value.concat([['world']]));//'helloworld'
var value = ['hello'];
console.log(value.concat('world'));//["hello", "world"]
console.log(value.concat(['world']));//["hello", "world"]
console.log(value.concat([['world']]));//["hello", ["world"]]
创建
字符串和数组均提供 slice() 方法,分别用于创建子字符串和子数组。
slice() 方法基于当前数组(或字符串)中的一个或多个项创建一个新的数组(或字符串)。该方法接受一个或两个参数,分别指定要返回项的起始位置和结束位置,并返回新创建的对象。
slice(start, end) 方法需要 start 和 end 两个参数,返回从 start 位置开始到 end 位置(不包含 end)的子数组(或子字符串)。如果 end 参数为 undefined 或未提供,则返回从 start 位置到原数组(或字符串)末尾的所有项。
如果 start 参数为负数,则实际起始位置计算为 max(length + start, 0)。
如果 end 参数为负数,则实际结束位置计算为 max(length + end, 0)。
start 和 end 参数的位置不可交换,否则会影响截取结果。
var numbers = [1,2,3,4,5];
console.log(numbers.slice(2));//[3,4,5]
console.log(numbers.slice(2,undefined));//[3,4,5]
console.log(numbers.slice(2,3));//[3]
console.log(numbers.slice(2,1));//[]
console.log(numbers.slice(-3));//-3+5=2 -> [3,4,5]
console.log(numbers.slice(-8));//max(5 + -8,0)=0 -> [1,2,3,4,5]
console.log(numbers.slice(0,-3));//-3+5=2 -> [1,2]
console.log(numbers.slice(-2,-1));//-2+5=3;-1+5=4; -> [4]
var stringValue = 'hello world';
console.log(stringValue.slice());//'hello world'
console.log(stringValue.slice(2));//'llo world'
console.log(stringValue.slice(20));//''
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(-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'
位置查找方法对比
位置
字符串和数组都提供了查找位置的两个方法:indexOf() 和 lastIndexOf()。位置查找方法与方括号 [] 读取方法互为逆向操作:前者通过项查找索引,后者通过索引查找项。
【indexOf()】
indexOf(search, start) 方法接收 search 和 start 两个参数,返回 search 值首次出现的位置索引;若未找到,则返回 -1。
在字符串中,search 参数会调用 String() 转型函数,将非字符串值转换为字符串进行比较;而在数组中,search 参数使用严格相等运算符(===)进行类型和值的比较。
对于第二个参数 start,无论是数组还是字符串,都会隐式调用 Number() 转型函数,将非数字值(undefined 除外)转换为数值。若忽略该参数或值为 undefined、NaN,则 start 默认为 0。
若 start 参数为负数,字符串的处理逻辑是将 start 重置为 0;而数组的处理逻辑是 start = max(0, start + length)。
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
var arr = ['a','b','c','d','e','a','b'];
console.log(arr.indexOf('a',undefined));//0
console.log(arr.indexOf('a',NaN));//0
console.log(arr.indexOf('a',1));//5
console.log(arr.indexOf('a',true));//5
console.log(arr.indexOf('a',-1));//max(0,-1+7)=6; -1
console.log(arr.indexOf('a',-5));//max(0,-5+7)=2; 5
console.log(arr.indexOf('a',-50));//max(0,-50+7)=0; 0
【lastIndexOf()】
与 indexOf() 相反,lastIndexOf() 方法从右向左进行查找。
lastIndexOf(search, start) 方法接收 search 和 start 两个参数,返回 search 字符串最后一次出现的位置;若未找到,则返回 -1。
同样地,在字符串中,search 参数会调用 String() 转型函数,将非字符串值转换为字符串;而在数组中,search 参数使用严格相等运算符(===)进行比较。
对于第二个参数 start,无论是数组还是字符串,都会隐式调用 Number() 转型函数,将非数字值(undefined 除外)转换为数值。
若忽略该参数或值为 undefined、NaN,字符串的处理逻辑是 start = length - 1;而数组的处理逻辑是 start = 0。
若 start 参数为负数,字符串的处理逻辑是将 start 重置为 0;而数组的处理逻辑是 start = max(0, start + length)。
var string = 'hello world world';
console.log(string.lastIndexOf('ld'));//15
console.log(string.lastIndexOf('ld',undefined));//15
console.log(string.lastIndexOf('ld',NaN));//15
console.log(string.lastIndexOf('ld',-1));//-1
console.log(string.lastIndexOf('h',-1));//0
console.log(string.lastIndexOf('w',undefined));//12
console.log(string.lastIndexOf('ld',10));//9
console.log(string.lastIndexOf('ld',[10]));//9
console.log(string.lastIndexOf('true',[10]));//-1
console.log(string.lastIndexOf(false,[10]));//-1
var arr = [1,2,3,'1','2','3'];
console.log(arr.lastIndexOf('2'));//4
console.log(arr.lastIndexOf(3));//2
console.log(arr.lastIndexOf(0));//-1
var arr = ['a','b','c','d','e','a','b'];
console.log(arr.lastIndexOf('b'));//6
console.log(arr.lastIndexOf('b',undefined));//-1
console.log(arr.lastIndexOf('a',undefined));//0
console.log(arr.lastIndexOf('b',NaN));//-1
console.log(arr.lastIndexOf('b',1));//1
console.log(arr.lastIndexOf('b',-1));//max(0,-1+7)=6; 6
console.log(arr.lastIndexOf('b',-5));//max(0,-5+7)=2; 1
console.log(arr.lastIndexOf('b',-50));//max(0,-50+7)=0; -1
以上关于 JavaScript 中数组和字符串方法对比的内容到此结束,希望能为读者提供有价值的参考。