JavaScript字符串与数组的深入
字符串经常被当作字符数组。字符串的内部实现究竟有没有使用数组并不好说,但 JavaScript 中的字符串和字符数组并不是一回事,最多只是看上去相似而已。
例如下面两个值:
var a = "foo"; var b = ["f","o","o"];
字符串和数组的确很相似,它们都是类数组,都有 length 属性以及 indexOf() 和 concat() 方法:
a.length; // 3 b.length; // 3 a.indexOf("o"); // 1 b.indexOf("o"); // 1 var c = a.concat("bar"); // "foobar" var d = b.concat(["b","a","r"]); // ["f","o","o","b","a","r"]
但这并不意味着它们都是”字符数组“,比如:
a[1] = "O"; b[1] = "O"; a; // "foo" b; // ["f","O","o"]
JavaScript 中字符串是不可变的,而数组是可变的。并且 a[1] 在 JavaScript 中并非总是合法语法,在老版本的 IE 中就不被允许。正确的方法应该是 a.charAt(1)
字符串不可变是指字符串的成员函数不会改变原始值,而是创建并返回一个新的字符串。而数组的成员函数都是在其原始值上进行操作。
c = a.toUpperCase(); a === c; // false a; // "foo" c; // "FOO"
许多数组函数用来处理字符串很方便。虽然字符串没有这些函数,但可以通过”借用“数组的非变更方法来处理字符串:
a.join; // undefined a.map; // undefined var c = Array.prototype.join.call( a, "-"); var d = Array.prototype.map.call( a, function(v){ return v.toUpperCase() + "."; } ).join( "" ); c; // "f-o-o" d; // "F.O.O"
另一个不同点在于字符串反转。
数组有一个字符串没有的可变更成员函数 reverse():
a.reverse; // undefined b.reverse(); // ["o","O","f"] b; // ["f","O","o"]
因为字符串是不可变的,所以无法”借用“数组的可变更成员函数
一个变通的办法是先将字符串转换为数组,待处理完后再将结果转换回字符串:
var c = a.split("").reverse().join(""); c; // "oof"
这种方法简单粗暴,但对简单的字符串却完全适用。
如果需要经常以字符数组的方式来处理字符串的话,倒不如直接使用数组。这样就不用在字符串和数组之间来回折腾。可以在需要时使用 join("") 将字符数组转换为字符串。