推荐使用 str[0] 和 str.slice(1) 获取首字符和剩余字符串,因其安全、高效、语义清晰;解构赋值虽简洁但对 emoji 等 Unicode 字符易出错,且 rest 需 join 才得子串。

用解构赋值直接取首字符和剩余部分
JavaScript 的数组解构语法可以无缝用于字符串,因为字符串在解构时会被隐式转为可迭代对象(每个字符一个元素)。不需要先 split('') 或 Array.from(),直接写 const [first, ...rest] = str 就行。
常见错误是误以为必须转成数组才能解构——其实不用。但要注意:这种解构按 UTF-16 编码单元拆分,对 emoji 或增补平面字符(如 ?、??)可能切错位置。
-
const [first, ...rest] = "hello"→first === "h",rest === ["e", "l", "l", "o"] -
const [a, b, ...c] = "ab cd"→a === "a",b === "b",c === [" ", "c", "d"] - 若字符串为空,
first为undefined,rest为空数组[]
处理 emoji 和 Unicode 超出 BMP 的字符
默认解构会把代理对(surrogate pair)拆成两个 \uXXXX 单元,导致首字符取错。比如 "?" 实际占两个码元,解构出的 first 是前半段乱码。
正确做法是先用 Array.from(str) 或扩展运算符 [...str] 基于 Unicode 码点解析,再解构:
-
const chars = [..."?abc"]→["?", "a", "b", "c"](4 个元素) -
const [first, ...rest] = [..."?abc"]→first === "?",安全 - 性能上,
[...str]比Array.from(str)稍快,两者都比正则匹配可靠
想获取“剩余字符串”而非字符数组?别忘了 join
解构得到的 rest 是字符数组,不是子串。如果目标是 "ello" 这样的字符串,得手动 rest.join('')。
容易忽略的点:空字符串或单字符时,rest.join('') 返回空串,行为符合预期;但若后续要频繁拼接,注意 join 是线性时间操作,大量调用需权衡。
-
const [first, ...rest] = "hello"; const tail = rest.join('')→tail === "ello" -
const [first] = "x"→first === "x",rest未定义,不能直接rest.join - 稳妥写法:
const tail = rest?.join('') ?? ''
替代方案:slice 比解构更轻量且语义清晰
如果只取首字符和剩余文本,不涉及多变量提取,str[0] 和 str.slice(1) 更直接、无兼容性问题、不触发迭代器、对所有字符安全。
解构本质是语法糖,底层仍需遍历;而 slice 是原生字符串方法,V8 等引擎高度优化。尤其在循环中频繁调用时,差异明显。
-
const first = str[0]; const tail = str.slice(1)—— 推荐用于纯首/尾提取场景 -
str[0]对空字符串返回undefined,slice(1)返回空串,行为一致 - 不支持 IE8 及更早版本,但现代项目基本无影响;若需兼容,可用
str.charAt(0)替代str[0]
str[0] 和 str.slice(1) 才是多数情况下的实际选择——没陷阱,不歧义,也不依赖迭代器实现细节。

















