一、经典面试题:字符串逆序输出
题目描述
请将字符串hello进行反向输出。
二、不同水平的解法对比
1. 新手小白思路:循环遍历法
function reverseString(str) {
for (let i = str.length - 1; i >= 0; i--) {
console.log(str[i]); // 逐字符输出(非拼接返回)
}
}
// 调用示例:reverseString("hello"); // 输出:o l l e h(逐行打印)
大佬做法:数组方法链
function reverseString(str) {
return str.split('') // 拆分为字符数组
.reverse() // 数组逆序
.join(''); // 拼接为字符串
}
console.log(reverseString("hello")); // 输出:"olleh"
顶级大佬做法:箭头函数
const reverseString = str => str.split('').reverse().join('');
console.log(reverseString("hello")); // 输出:"olleh"
三、面试官灵魂追问:字符串的 "点操作" 原理
问题拆解
为什么简单数据类型string
能调用split()
、reverse()
等方法?
(类似问题:数字1
为何能调用toString()
?布尔值true
为何有valueOf()
方法?)
核心原理:包装类(Wrapper Class)机制
1. JS 数据类型的双重身份
数据类型 | 基本类型(Primitive) | 包装类型(Wrapper Object) |
---|---|---|
字符串(String) | 'hello' | String 对象 |
数字(Number) | 123 | Number 对象 |
布尔值(Boolean) | true | Boolean 对象 |
2. 包装类的自动转换过程
当对基本类型调用方法时,JS 会执行以下三步隐式操作:
let tmp = new String(str)
tmp.split('')
tmp立即销毁
- 创建包装对象:
new String(str)
生成临时String
对象 - 调用方法:在对象上执行
split('')
方法 - 销毁对象:方法执行完毕后,临时对象被垃圾回收
3. 重要特性对比
操作场景 | 基本类型行为 | 包装对象行为 |
---|---|---|
typeof str | "string" | "object" |
str instanceof String | false (非对象) | true (是 String 实例) |
内存存储 | 栈内存直接存储值 | 堆内存存储对象引用 |
4. 面试陷阱:包装类的坑
const a = 'hello'; // 基本类型
const b = new String('hello'); // 包装对象
console.log(a === b); // false(类型不同:string vs object)
console.log(a == b); // true(对象自动拆箱为 string)
原理:
==
触发类型转换:对象通过valueOf()
转换为基本类型再比较===
严格校验类型和值,故结果为false
四、扩展:箭头函数的核心特性
为什么顶级大佬解法选择箭头函数?
箭头函数 vs 传统函数
特性 | 传统函数(function ) | 箭头函数(=> ) |
---|---|---|
this 指向 | 动态绑定(调用时确定) | 继承外层作用域的 this |
arguments 对象 | 自动生成类数组 | 无,需用 ...rest 替代 |
prototype 属性 | 有(用于构造函数) | 无(不能作为构造函数) |
new 调用 | 可创建实例 | 报错(无 constructor ) |
典型应用场景:
- 回调函数(如
array.map()
、setTimeout
) - 需要保持
this
一致性的场景(如 React 组件)
五、总结
1. 字符串逆序核心解法
- 最优实践:利用数组方法链(
split
→reverse
→join
) - 代码简洁性:箭头函数适用于非复杂逻辑的函数定义
2. 包装类核心考点
- 基本类型调用方法时,JS 自动创建临时包装对象
- 避免显式使用
new String()
等装箱操作,优先使用基本类型
3. 面试应答策略
- 当被问 "基础类型为何能调用方法" 时,直接关联包装类的三步转换机制
- 用具体示例(如
str.split('')
的底层逻辑)辅助阐述原理