白菜刷LeetCode记-344. Reverse String
开始尝试用JavaScript来刷LeetCode,对前端又白又菜,那这次刷题就直接叫白菜的刷LeetCode旅程了。
今天的题目是很简单的字符串首尾交换,题目如下:
一开始自己的代码如下:
1 /** 2 * @param {string} s 3 * @return {string} 4 */ 5 var reverseString = function(s) { 6 let i = 0, j = s.length - 1, tmp; 7 while(i < j){ 8 tmp = s[i]; 9 s[i] = s[j]; 10 s[j] = tmp; 11 i++; 12 j--; 13 } 14 15 return s; 16 };
当然这样做得到的结果是错误的,输出的结果跟原来一样,也就是“hello”经过自己代码后还是"hello"。
看了一下讨论区,具体的方法是先将字符串转化为数组,然后对数据进行反转,最后再拼接在一起,代码如下:
1 /** 2 * @param {string} s 3 * @return {string} 4 */ 5 var reverseString = function(s) { 6 7 const arr = s.split(''); 8 9 for(let i = 0, j = s.length - 1 ; i < j ; i++, j--){ 10 arr[i] = s[j]; 11 arr[j] = s[i]; 12 } 13 14 return arr.join(''); 15 };
还有一种直接调用数组自带的反转函数的方法,代码只需要一行,不仅对大神们于JavaScript自带函数的熟悉感到羡慕嫉妒恨啊,代码如下:
var reverseString = function(s) { return s.split('').reverse().join(''); };
感谢LeetCode讨论区大神们贡献的结果啊!
问题来了,为什么自己的代码会对原来数据没影响呢?
看了一下http://www.w3school.com.cn/jsref/jsref_obj_string.asp
里头有这么一段话:
需要注意的是,JavaScript 的字符串是不可变的(immutable),String 类定义的方法都不能改变字符串的内容。像 String.toUpperCase() 这样的方法,返回的是全新的字符串,而不是修改原始字符串。
在较早的 Netscape 代码基的 JavaScript 实现中(例如 Firefox 实现中),字符串的行为就像只读的字符数组。例如,从字符串 s 中提取第三个字符,可以用 s[2] 代替更加标准的 s.charAt(2)。此外,对字符串应用 for/in 循环时,它将枚举字符串中每个字符的数组下标(但要注意,ECMAScript 标准规定,不能枚举 length 属性)。因为字符串的数组行为不标准,所以应该避免使用它。
因此原来的代码的方法是错误的,因为JavaScript的字符串是不可变的,经过循环后,s还是原来的值。而且根据上面这段话,使用s[num]这种访问字符串中某一位字符的方法也是不规范的,应该用 s.charAt(num)来获取。