我们来系统地梳理一下 JavaScript 中字符串(String)和数组(Array)的这些常用基础函数。
理解这两者差异的关键在于一个核心概念:字符串是不可变的(Immutable),而数组是可变的(Mutable)。记住这一点,很多函数的行为就变得顺理成章了。
1. 字符串(String)- 不可变的字符序列
当你对一个字符串进行“修改”操作(如切片、分割)时,你永远不会改变原始字符串。相反,你会得到一个新的字符串。
1.1 长度 (length)
这是一个属性,不是函数,所以后面没有括号 () 。它返回字符串中字符的数量。
JavaScript
const str = 'Hello, World!';
console.log(str.length); // 输出: 13
1.2 切片 (Slicing)
用于从字符串中提取一部分,并返回一个新字符串。原始字符串不变。
有三个函数可以做这件事,但你应该优先使用 slice()。
-
slice(startIndex, endIndex)-
这是最常用、最推荐的方法。
-
它提取从
startIndex开始,到endIndex之前(不包括endIndex)的部分。 -
支持负数索引,表示从字符串末尾开始计算。
-1指的是最后一个字符。 -
如果省略
endIndex,则会提取到字符串末尾。
JavaScript
const str = 'JavaScript'; console.log(str.slice(0, 4)); // 'Java' (从索引0到4,不含4) console.log(str.slice(4)); // 'Script' (从索引4到末尾) console.log(str.slice(-6)); // 'Script' (从倒数第6个字符到末尾) console.log(str.slice(0, -6)); // 'Java' (从索引0到倒数第6个字符) -
-
substring(startIndex, endIndex)-
功能与
slice类似,但有两点关键不同:-
不支持负数索引,任何负数都会被当作
0。 -
如果
startIndex大于endIndex,它会自动交换两者。
-
-
由于这些行为可能导致混淆,一般不推荐使用。
-
-
substr(startIndex, length)-
已废弃(Deprecated),不应该在新的代码中使用。
-
它的第二个参数是长度,而不是结束索引,这常常是错误的根源。
-
切片小结:一律使用
slice()。它功能强大、行为可预测,是你唯一需要熟练掌握的字符串切片函数。
1.3 分割 (Splitting)
使用 split(separator) 函数,将一个字符串按照指定的分隔符,拆分成一个数组。
-
separator可以是字符串,也可以是正则表达式。 -
如果
separator是空字符串'',会将字符串的每个字符都拆分开。
JavaScript
const sentence = 'The-quick-brown-fox';
const words = sentence.split('-'); // 使用 '-' 分割
console.log(words); // 输出: ['The', 'quick', 'brown', 'fox']
const letters = 'abc'.split(''); // 使用空字符串分割
console.log(letters); // 输出: ['a', 'b', 'c']
const csv = 'one,two,three';
console.log(csv.split(',')); // 输出: ['one', 'two', 'three']
这是一个单向操作:String -> Array。它的逆操作是数组的 join() 方法。
2. 数组(Array)- 可变的数据列表
数组是可变的,这意味着很多操作会直接修改原始数组。这是与字符串最本质的区别。
2.1 长度 (length)
和字符串一样,length 是一个属性。但数组的 length 是可读可写的。你可以通过修改它来截断或延长数组。
JavaScript
const arr = [10, 20, 30, 40, 50];
console.log(arr.length); // 输出: 5
// 截断数组 (这是一个修改操作)
arr.length = 3;
console.log(arr); // 输出: [10, 20, 30]
// 延长数组,新增的项会是 empty (空位)
arr.length = 5;
console.log(arr); // 输出: [10, 20, 30, <2 empty items>]
2.2 切片 (Slicing) - 不修改原数组
slice(startIndex, endIndex)
-
数组的
slice()和字符串的slice()几乎完全一样! -
它提取数组的一部分,返回一个新数组,并且不会修改原始数组。
-
同样支持负数索引。
JavaScript
const originalArr = ['a', 'b', 'c', 'd', 'e'];
const newArr = originalArr.slice(1, 4); // 从索引1到4 (不含4)
console.log(newArr); // 输出: ['b', 'c', 'd']
console.log(originalArr); // 输出: ['a', 'b', 'c', 'd', 'e'] (原始数组不变)
2.3 分割/修改 (Splicing) - 修改原数组
你问题中提到的“数组的分割”,在JS语境下最接近的其实是 splice() 函数。它是一个非常强大的“瑞士军刀”,可以同时实现删除、插入和替换元素,但它会直接修改原始数组。
splice(startIndex, deleteCount, ...itemsToAdd)
-
startIndex: 开始修改的位置。 -
deleteCount: 从startIndex开始,要删除的元素数量。 -
...itemsToAdd: (可选) 要在startIndex位置插入的新元素。 -
返回值:一个包含被删除元素的数组。如果没有删除任何元素,则返回空数组。
使用场景:
-
仅删除:
JavaScript
const arr = ['a', 'b', 'c', 'd', 'e']; const deleted = arr.splice(1, 2); // 从索引1开始,删除2个元素 console.log(deleted); // 输出: ['b', 'c'] console.log(arr); // 输出: ['a', 'd', 'e'] (原数组被修改) -
仅插入:
JavaScript
const arr = ['a', 'd', 'e']; arr.splice(1, 0, 'x', 'y'); // 从索引1开始,删除0个元素,然后插入 'x' 和 'y' console.log(arr); // 输出: ['a', 'x', 'y', 'd', 'e'] (原数组被修改) -
替换 (删除并插入):
JavaScript
const arr = ['a', 'b', 'c', 'd', 'e']; arr.splice(1, 2, 'z'); // 从索引1开始,删除2个元素('b','c'),然后在该位置插入 'z' console.log(arr); // 输出: ['a', 'z', 'd', 'e'] (原数组被修改)
总结与记忆技巧
混淆主要发生在 slice 和 splice 之间,以及它们在字符串和数组上的行为。
| 操作 | 字符串 (String) - 不可变 | 数组 (Array) - 可变 | 如何记忆避免混淆 |
|---|---|---|---|
| 长度 | str.length (只读) |
arr.length (可读写) |
数组更“灵活”,长度可以被你手动改变。 |
| 切片 (取一部分) | slice() (返回新字符串) |
slice() (返回新数组) |
slice 是安全的“切片”。它就像从蛋糕上切下一块,既得到了新的一块,也没毁掉原来的蛋糕。行为在字符串和数组上高度一致,都是创建副本。 |
| 分割/修改 | split() (字符串 -> 数组) |
splice() (修改原数组) |
1. 拼写上的差异:splice 比 slice 多一个 p,你可以把 p 想象成 Permanent (永久的) 或者 Powerful (强大的),暗示它会造成永久性、更强力的修改。 2. 功能上的对立: split 是把一个东西(字符串)拆成一堆(数组),而 splice 是在一堆东西(数组)里进行“手术”(增/删/改)。它们的目标和应用场景完全不同。 |
核心记忆法则:
-
不变的字符串 vs 可变的数组:这是所有区别的根源。
-
slice是君子:它只拷贝,不动你的原数据。无论用在字符串还是数组上,都很“礼貌”。这是你的首选“切片”工具。 -
splice是刺客:它直接对原数组动刀(增、删、改)。名字里的p提醒你它的破坏性(Permanent change)。它的返回值是被它“干掉”的元素。 -
split和join是一对:string.split()把字符串变成数组,array.join()把数组变回字符串。它们是数据形态转换的桥梁。
当你准备操作数据时,先问自己一个问题:“我希望修改原始数据,还是得到一个副本?”
-
想得到副本?用
slice()。 -
想直接修改原数组?用
splice()。 -
想把字符串拆成数组?用
split()。
遵循这个思路,你就能清晰地选择正确的函数,避免混淆。