网站首页 > 知识剖析 正文
字符串逆序这件事,说难也难,说简单也简单。前端开发嘛,天天和字符串打交道,处理这种需求也是家常便饭。今天咱们就来聊聊,怎么把一个字符串倒过来写。
最直接的方法,大家都知道,API 一把梭。什么 split、reverse、join,三个组合技,轻轻松松搞定。但是,有些朋友可能就会问了:Array.prototype.reverse.call(s) 直接用这个不香吗?香是香,但……不太行。
为啥?因为 字符串不是数组。reverse 这是数组的原型方法,非数组用不了。你强行 call 上去,浏览器得懵:“哥,咱俩压根不是一类的,别勉强我。” 所以,不能直接拿 reverse.call 来搞字符串。不过咱也别急,办法还是有的。
API 派:三件套,稳
先看最经典的写法:
const reverse = (s) => s.split("").reverse().join("");
reverse("hello"); // => "olleh"
啥意思?一拆解就明白了:
- split(""):把字符串拆成一个个字符的小数组,比如 "hello" 变成 ["h", "e", "l", "l", "o"]。
- reverse():数组反转,["o", "l", "l", "e", "h"]。
- join(""):再把数组拼回字符串 "olleh"。
三个操作,一气呵成,优雅、简洁,这谁看了不说一句专业呢?
但如果你真的就拿 Array.prototype.reverse.call(s) 去用,嘿嘿,它直接报你个错:“s.reverse is not a function”,气不气人?因为 s 是字符串,人家没有 reverse 这个方法,call 也白搭。
所以,想用 reverse,必须得先把字符串变成数组,这也解释了为啥 split 这一步必不可少。
手写派:不靠 API,自力更生
有的朋友可能不屑了:“用 API 多没劲,写代码不就为了秀操作吗?” 那行,来个纯手写版,撸起袖子,咱干!
function reverse(s) {
let r = "";
for (const c of s) {
r = c + r;
}
return r;
}
reverse("hello"); // => "olleh"
看着简单,其实小巧思满满。逐个拿出字符串里的每个字符,每次都插到新字符串的最前面。这不就倒过来了?
要我说,这种写法虽然不复杂,但是真有点“笨办法最可靠”的味道。尤其是当面试官问你:“能不用 API 写个字符串反转吗?” 你要是能当场写出来,立马加分。
不过,这种手写法也有点小问题。如果字符串特别长,比如几万个字符,这种方式就会不断地拼接字符串,性能可能有点拉胯。毕竟,字符串在 JS 里是不可变的,拼接其实是在不停地创建新字符串,换句话说就是在疯狂申请新内存,这样搞效率不高。
双指针派:更高效一点
要说秀操作,其实还有一种写法,稍微高效点——双指针,这可是刷算法题的标配:
function reverse(s) {
const arr = s.split("");
let left = 0, right = arr.length - 1;
while (left < right) {
[arr[left], arr[right]] = [arr[right], arr[left]];
left++;
right--;
}
return arr.join("");
}
reverse("hello"); // => "olleh"
思路特别清晰,左右两边往中间夹,互换位置。和数组反转是一个套路。为什么要先 split 呢?因为咱还是得把字符串变成数组,才能在原地交换元素。
这种方法的优势在哪?内存利用率高,字符串被转成数组以后,在数组内部就地反转,最后再拼回字符串,速度更快,尤其是长字符串更明显。
那reverse.call(s)到底能不能用?
咱绕回最开始的问题,能不能直接用 Array.prototype.reverse.call(s) 来逆序字符串?答案很明确:不能。因为 reverse 是数组专属的,字符串不吃这一套。
如果你非得秀一波骚操作,可以这么写:
Array.prototype.reverse.call(s.split(""));
或者更完整点:
[].reverse.call(s.split(""));
但问题来了:既然都 split 了,干嘛还这么麻烦?直接用 s.split("").reverse().join("") 不香吗?所以这个方法更多是用来秀知识点,不是真正的实用招。
总结一句,字符串反转这种操作,说白了看场合。要简单省事,API 直接干;要秀一波操作,手写法或者双指针上场;要解释原理,别忘了字符串不是数组,不能直接用 reverse。
说到底,开发嘛,灵活点就行,该用 API 就用,别死磕。但底层原理心里有点数,关键时刻不掉链子,才是正经事。
猜你喜欢
- 2025-05-02 JS 写正则表达式,判断是否为手机号
- 2025-05-02 JS 类型检测:谈 typeof 和 instanceof 的缺陷与优化
- 2025-05-02 零起点Python机器学习快速入门-4-3-字符串常用方法
- 2025-05-02 输出、同步和异步(同步和异步输入信号的区别)
- 2025-05-02 最快清除数组空值?分享 1 段优质 JS 代码片段!
- 2025-05-02 JS 克隆对象八种技术,为何少不了 StructuredClone?
- 2025-05-02 C语言字符串操作总结大全(超详细)
- 2025-05-02 推荐一个检测 JS 内存泄漏的神器(js内存泄漏的原因及解决办法)
- 2025-05-02 模拟 Vue 中 JS 动态表达式在模版中被动态解析的实现
- 2025-05-02 解决 JS 对象中继承性问题之方式一:通过原型链继承来解决继承问题
- 05-05vin码怎么查车型?车辆VIN码的第十位代表什么信息?
- 05-05Java数组数据的操作之检查日期格式是否正确
- 05-05苹果序列号怎么看生产日期和产地?
- 05-05参考文献中的M J N D字母代表什么?
- 05-05闲鱼交易技巧,满满的干货(闲鱼的交易流程怎么样的?我是买家)
- 05-05忘记自已多少岁了?可试试年龄计算器
- 05-05汽车-剖析、解析车架号(VIN)中的第10位-车型年份
- 05-05干货|史上最全波特酒年份指南(波特酒 年份)
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)