首页
/ es-toolkit 兼容版 `pad` 函数详解:双向填充字符串的兼容实现与源码剖析

es-toolkit 兼容版 `pad` 函数详解:双向填充字符串的兼容实现与源码剖析

2026-09-15 16:45:27作者:虞亚竹Luna

pad 是 es-toolkit 提供的字符串填充工具,用于将字符串在左右两侧补齐指定字符以达到目标长度。本文以 docs/compat/reference/string/pad.md 为主体,深入讲解 es-toolkit/compat 兼容版 pad 的用法、参数规则、与主版本 es-toolkit/string 的差异,以及其底层实现原理(多字节字符处理、null/undefined 容错、字符截断策略),帮助你在迁移 Lodash 或对齐旧代码行为时正确选择和使用该 API。

一、pad 是什么:函数签名与核心语义

pad 在字符串长度不足目标长度时,用指定的填充字符在字符串左右两侧同时补齐。当填充字符无法被均匀分割时,多余的一个字符放在右侧

const padded = pad(str, length, chars);

完整签名如下(来自 src/compat/string/pad.ts):

export function pad(str?: any, length: any = 0, chars: any = ' '): string;

参数说明

参数 类型 是否必填 默认值 说明
str string 可选 需要填充的字符串
length number 可选 0 填充后要达到的目标长度
chars string 可选 ' '(空格) 用于填充的字符

返回值

string):返回填充后达到指定长度的字符串;若无需填充则返回原字符串。

基础示例

import { pad } from 'es-toolkit/compat';

// 使用默认空格填充
pad('abc', 8);
// Returns: '  abc   '

// 使用指定字符填充
pad('abc', 8, '_-');
// Returns: '_-abc_-_'

// 已达标时原样返回
pad('abc', 3);
// Returns: 'abc'

// 目标长度更短时原样返回
pad('abc', 2);
// Returns: 'abc'

从上面的例子可以看出两个关键规则:

  1. 左短右长pad('abc', 8) 左侧补 2 个空格、右侧补 3 个空格,余数给右侧;
  2. 不足不补:当 length <= str.length 时,无论目标长度多短,都直接返回原字符串(测试用例 src/compat/string/pad.spec.ts 明确验证了这一点)。

二、nullundefined 的特殊处理

compat 版本与主版本最大的行为差异在于对空值的处理。nullundefined 会被当作空字符串处理,这是为了与 Lodash 保持兼容:

import { pad } from 'es-toolkit/compat';

pad(null, 5); // '     '
pad(undefined, 3, '*'); // '***'

测试用例进一步验证了该行为的一致性(见 src/compat/string/pad.spec.ts):

pad(null, 2); // '  '
pad(undefined, 2); // '  '
pad('', 2); // '  '
pad(null, 2, '_-'); // '__'
pad(undefined, 2, '_-'); // '__'

这里 nullundefined 与空字符串 '' 三者行为完全一致——这正是文档中提示“该函数因处理 nullundefined 而运行较慢”的原因所在。

三、compat 版与主版本:如何选择

文档开头给出了明确建议:优先使用主版本 es-toolkit/stringpad,因为 compat 版为了兼容 Lodash 的容错行为(处理 null/undefined)付出了额外的性能代价。

主版本文档见 docs/reference/string/pad.md,其实现位于 src/string/pad.ts,直接基于原生 API,极为简洁:

export function pad(str: string, length: number, chars = ' '): string {
  return str.padStart(Math.floor((length - str.length) / 2) + str.length, chars).padEnd(length, chars);
}

主版本与 compat 版本的主要差异对比:

维度 es-toolkit/string(主版本) es-toolkit/compat(兼容版)
导入路径 es-toolkit/string es-toolkit/compat
参数类型 严格 string 宽松(任意类型会做隐式转换)
null/undefined 不适用(类型层面即拒绝) 视为空字符串
实现方式 原生 padStart/padEnd 内部 createPadding + 多字节字符处理
性能 更快 稍慢(需容错处理)

选择建议:

  • 新代码:优先使用 es-toolkit/string 的 pad,类型更严格、性能更好;
  • 从 Lodash 迁移:当原代码依赖 Lodash 的宽松行为(如传入 null、数字、可转字符串对象)时,使用 es-toolkit/compatpad 可做到行为对齐,无需逐处改写。

四、源码级原理剖析:pad 的实现与关键调用链

4.1 主流程:三步骤实现

compat 版 pad 的实现非常紧凑(src/compat/string/pad.ts):

export function pad(str?: any, length: any = 0, chars: any = ' '): string {
  const value = toString(str);
  const targetLength = toInteger(length);
  const strLength = stringSize(value);

  if (targetLength <= strLength) {
    return value;
  }

  const mid = (targetLength - strLength) / 2;
  const padChars = `${chars}`;

  return createPadding(Math.floor(mid), padChars) + value + createPadding(Math.ceil(mid), padChars);
}

整个流程分为四步:

  1. 类型归一化toString(str) 将任意输入转为字符串(null''),toInteger(length) 将长度参数取整(负数和 0 都归为 0,字符串 '4' 会被转为数字 4);
  2. 提前返回targetLength <= strLength 时直接返回原字符串,不做任何填充;
  3. 计算分配mid = (targetLength - strLength) / 2,左侧取 Math.floor(mid)、右侧取 Math.ceil(mid)——这正是“多余字符放右侧”的实现来源;
  4. 拼接结果:左右两侧分别调用 createPadding 生成填充串,再与原文拼接。

4.2 核心工具:stringSizecreatePadding

两侧填充的核心逻辑在 src/compat/_internal/createPadding.ts

export function stringSize(str: string): number {
  return regexMultiByte.test(str) ? Array.from(str).length : str.length;
}

export function createPadding(length: number, chars: string): string {
  const charsLength = stringSize(chars);

  if (charsLength === 0 || length < 1) {
    return '';
  }

  const result = chars.repeat(Math.ceil(length / charsLength));

  return regexMultiByte.test(result) ? Array.from(result).slice(0, length).join('') : result.slice(0, length);
}

这里有三个值得注意的实现细节:

  • 多字节字符按码点计数stringSize 通过 regexMultiByte(定义于 src/compat/_internal/regexMultiByte.ts,匹配零宽连接符、星面平面码点、组合变音符等)检测字符串是否含特殊 Unicode 字符;若包含,则用 Array.from(str).length 按 Unicode 码点计数,而不是用可能切分代理对的 str.length
  • 循环填充 + 截断:先用 chars.repeat(Math.ceil(length / charsLength)) 生成足够长的填充串,再精确截取 length 个字符,避免多字节字符被截断成乱码;
  • 空字符短路:当 chars 长度为 0 或所需长度小于 1 时直接返回空串——测试中 pad('abc', 6, '') 返回 'abc'(见 src/compat/string/pad.spec.ts)正是依赖此分支。

4.3 多字节字符的正确性由测试保障

src/compat/string/pad.spec.ts 中有专门的 emoji 测试用例:

pad('ab', 8, '😀'); // '😀😀😀ab😀😀😀'
pad('😀😁😂', 8, '_'); // '__😀😁😂___'

第一个用例中 3 个 emoji 恰好凑满 6 个填充位,说明 length码点数量而非 UTF-16 单元计数;若按 str.length(emoji 占 2 个单元)计算,结果将出现截断残缺。这也是 compat 版不直接使用原生 padStart/padEnd(它们按 UTF-16 单元计数)而要自建 createPadding 的根本原因。

五、兼容行为细节:类型强制与边界情况

5.1 length 会被强制为整数

compat 版通过 toIntegerlength 做取整与归零处理,测试覆盖了以下边界(src/compat/string/pad.spec.ts):

// 负数按 0 处理
pad('abc', -2); // 'abc'

// 字符串数字会被强制转换
pad('abc', '4'); // 'abc '('4' 被转为 4,补 1 个空格)
pad('abc', ''); // 'abc'('' 被转为 0)

5.2 str 会被强制为字符串

与 Lodash 一致,str 参数接受任意可字符串化的对象(src/compat/string/pad.spec.ts):

pad(Object('abc'), 6); // ' abc  '(包装对象)
pad({ toString: () => 'abc' }, 6); // ' abc  '(自定义 toString)

5.3 chars 为空串时返回原字符串

chars 被强转为空字符串时(如 '' 或空包装对象),函数直接返回原字符串(src/compat/string/pad.spec.ts):

pad('abc', 6, ''); // 'abc'
pad('abc', 6, Object('')); // 'abc'

六、与兄弟函数 padStartpadEnd 的关系

pad 并非孤立存在,compat 目录下还有两个同族函数:

三者的实现骨架完全一致(toStringtoIntegerstringSizecreatePadding),区别仅在于填充位置的组合方式:pad 等价于“左侧 floor(mid) + 右侧 ceil(mid)”的合体。当你只需要单侧对齐(如生成表格列)时,应优先选择 padStart/padEnd 以获得更清晰的语义;需要居中效果(如标题横幅)时才使用 pad

七、从哪里导入:导出路径速查

pad 在 es-toolkit 中的导出位置如下:

  • compat 版本:由 src/compat/compat.ts 统一导出,使用时 import { pad } from 'es-toolkit/compat'
  • 主版本:由 src/string/index.ts 导出,使用时 import { pad } from 'es-toolkit/string'

如果你同时在迁移多个 Lodash 字符串函数,建议对照 docs/compat/reference/string 目录下的其他参考文档(如 padStartpadEndtrim 等)统一规划导入来源,避免混用两套语义产生行为差异。

总结

  • es-toolkit/compatpad(str, length, chars) 对字符串两侧进行填充,length 不足时原样返回,余数填充在右侧;
  • 它完整继承了 Lodash 的宽松兼容行为:null/undefined 视为空字符串、参数自动强转、支持多字节字符按码点计数填充;
  • 底层由 toStringtoIntegerstringSizecreatePadding 组成的调用链实现(见 src/compat/string/pad.tssrc/compat/_internal/createPadding.ts),行为正确性由 src/compat/string/pad.spec.ts 的完整测试覆盖;
  • 新代码建议优先使用更快的 es-toolkit/string 主版本 pad;仅当需要对齐 Lodash 兼容语义时,才选用 es-toolkit/compat 版本。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
34
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.21 K
2.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
949
1.87 K
docsdocs
暂无描述
Markdown
906
5.84 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
537
612
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
864
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
4.29 K
1.04 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.39 K
1.48 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
550
401
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.19 K
348