字符串处理实战:模板字符串、split/join、正则的 80% 用法

前言

前端里接口参数拼接、搜索条件、富文本简单处理,几乎都绕不开字符串:拼 URL、拆 query替换/截断文案。很多人习惯用 + 拼到眼花,或者到处 indexOf/substring,写多了难维护也容易出 bug。

用**模板字符串split/join正则**这三类能力,可以把「替换/匹配」写得更短、更稳。本文用 10 个左右常见场景,把日常该怎么选、为什么这么选、容易踩的坑讲清楚,只讲 80% 会用到的部分,不求覆盖所有正则语法。

适合读者:

  • 会写 JS,但对模板字符串/正则什么时候用、怎么写有点模糊
  • 刚学 JS,希望一开始就养成清晰的字符串写法
  • 有经验的前端,想统一团队里的 URL 拼接、搜索条件、简单富文本处理

一、先搞清楚:模板字符串split/join正则分别在干什么

能力 在干什么 典型用法
模板字符串 用 ````` 和 ${} 把变量嵌进字符串,支持换行 URL、拼文案、多行字符串
split 按分隔符把字符串拆成数组 query 拆成键值对、按逗号/换行拆列表
join 把数组用分隔符拼成字符串 把参数数组拼成 query、把标签数组拼成文案
正则 按模式匹配、替换、提取 替换占位符、校验格式、简单富文本处理
javascript 复制代码
// 传统 + 拼接:多参数时很难看
const url = baseUrl + '/api/user?id=' + id + '&name=' + encodeURIComponent(name);

// 模板字符串:一眼看出「URL 长什么样」
const url = `${baseUrl}/api/user?id=${id}&name=${encodeURIComponent(name)}`;

记住一点:能一眼看出「最终长什么样」就用模板字符串;要「按规则拆开或拼起来」就用 split/join;要「按模式匹配或替换」就用正则

二、模板字符串的常见用法

1. 接口 URLquery 拼接(模板字符串 + 一层编码)

应用场景

  • 你要调一个列表接口(比如商品列表、用户列表),需要把「搜索关键词」「页码」「每页显示多少条」这些信息拼在接口地址后面,比如拼出 ?keyword=张三&page=1&pageSize=10 这种格式。

先搞懂一个核心问题:为啥不能直接拼?

  • 就像咱们寄快递要写规范的地址(省 - 市 - 区 - 街道),URL(接口地址)也有自己的「书写规范」------ 有些字符(比如中文、空格、&、=)直接写进去,服务器会 "看不懂",甚至理解错意思。

举个最直白的例子

你要搜「用户 输入」(关键词里有空格),如果直接拼地址:/api/list?keyword=用户 输入&page=1

服务器会把「空格」当成 "参数分隔符",以为「keyword = 用户」是一个参数,「输入 & page=1」是另一个参数,直接解析错了!

javascript 复制代码
const baseUrl = '/api/list'; // 接口基础地址
const params = {
  keyword: '用户 输入',  // 要搜索的关键词(有中文+空格,是"违规字符")
  page: 1,              // 第1页
  pageSize: 10          // 每页显示10条
};

// ✅ 推荐写法:用 URLSearchParams 当"翻译官"(自动处理违规字符)
// 你可以把 URLSearchParams 理解成:专门处理URL参数的"小工具"
const query = new URLSearchParams({
  keyword: params.keyword,
  page: String(params.page),    // 这个小工具只认字符串,数字要转一下
  pageSize: String(params.pageSize),
}).toString(); // 把处理好的参数转成字符串

// 用模板字符串拼最终地址,结构一眼能看懂
const url = `${baseUrl}?${query}`;
console.log('自动处理后的地址:', url);
// 输出:/api/list?keyword=%E7%94%A8%E6%88%B7+%E8%BE%93%E5%85%A5&page=1&pageSize=10
// 你看:"用户 输入"被翻译成了 %E7%94%A8%E6%88%B7+%E8%BE%93%E5%85%A5,服务器能看懂了!

// ❌ 反面示例:直接拼(不翻译违规字符)------ 服务器看不懂
const badUrl1 = `${baseUrl}?keyword=${params.keyword}&page=${params.page}&pageSize=${params.pageSize}`;
console.log('直接拼的错误地址:', badUrl1);
// 输出:/api/list?keyword=用户 输入&page=1&pageSize=10(空格、中文没翻译,服务器解析错)

// ⚠️ 手动翻译写法(麻烦,容易漏):
// encodeURIComponent 就是"单个字符翻译器",只能翻译一个参数值
const encodedKeyword = encodeURIComponent(params.keyword); // 只翻译关键词
const encodedPage = encodeURIComponent(params.page);       // 翻译页码
const encodedPageSize = encodeURIComponent(params.pageSize); // 翻译每页条数
const goodUrlByHand = `${baseUrl}?keyword=${encodedKeyword}&page=${encodedPage}&pageSize=${encodedPageSize}`;
console.log('手动翻译的正确地址:', goodUrlByHand);
// 输出和自动处理的一样,但要写3次 encodeURIComponent,参数多了容易漏!

更直观的表格说明

名词 小白版解释 什么时候用
encodeURIComponent 单个 URL 参数的 "翻译器":把中文、空格这些服务器看不懂的字符,翻译成服务器能懂的 "编码"(比如把 "用户" 译成 % E7%94% A8% E6%88% B7 手动拼接 URL 参数时,给每个参数值单独翻译
URLSearchParams 批量处理 URL 参数的 "智能翻译机":你把所有参数丢给它,它会自动调用 encodeURIComponent 给每个参数翻译,还能拼成规范的参数串 推荐优先用!不管参数多少,一次搞定,不翻车

关键注意点(小白必看)

  1. 只要参数里有中文空格&= 这些字符,就必须 "翻译",否则接口会调失败 / 返回错误数据;
  2. URLSearchParams 是 "懒人神器":不用记 encodeURIComponent 怎么写,不用怕漏翻译某个参数,丢进去就自动处理;
  3. 小细节:URLSearchParams 只认字符串,所以数字类型的参数(比如 page:1)要转成 String (page),否则会报错。

2. 搜索条件:有值才带参数(过滤掉空值再拼)

场景: 只有 keyword 有值才带 keyword,只有 status 有值才带 status,避免 ?keyword=&status= 这种无意义参数。

javascript 复制代码
const baseUrl = '/api/search';
const search = {
  keyword: '张三',  // 有实际值
  status: '',       // 空值(无意义)
  type: '1',        // 有实际值
};

// 第一步:筛选出非空的参数(去掉空字符串、全空格、null/undefined)
// Object.entries:把对象拆成[key, value]的数组,方便批量检查
// filter:筛选器,只留满足条件的参数
// trim():去掉字符串前后空格(比如用户只输空格也算空值)
const filtered = Object.fromEntries(
  Object.entries(search).filter(([_, value]) => {
    // 条件:值不是null/undefined,且去掉空格后不是空字符串
    return value != null && String(value).trim() !== '';
  })
);

// 第二步:用URLSearchParams自动编码参数,转成query字符串
const query = new URLSearchParams(filtered).toString();

// 第三步:拼接最终URL(有参数加?,没参数直接用基础地址)
const url = query ? `${baseUrl}?${query}` : baseUrl;
// 最终结果:/api/search?keyword=%E5%BC%A0%E4%B8%89&type=1
// 对比:如果没过滤,会是 /api/search?keyword=%E5%BC%A0%E4%B8%89&status=&type=1(多了无用的status=)
);
const query = new URLSearchParams(filtered).toString();
const url = query ? `${baseUrl}?${query}` : baseUrl;
// /api/search?keyword=%E5%BC%A0%E4%B8%89&type=1

核心名词小白解释:

代码片段 通俗理解
Object.entries(search) {keyword:'张三', status:'', type:'1'}拆成[['keyword','张三'], ['status',''], ['type','1']],方便逐个检查值是否为空
Object.fromEntries(数组) 把筛选后的数组(比如[['keyword','张三'], ['type','1']])还原成对象{keyword:'张三', type:'1'}
value.trim() 去掉字符串前后的空格,比如' 张三 '变'张三',' '变空字符串(避免 "只输空格" 被当成有效值)
filter(...) 只保留 "非空" 的参数,把status:''这种空值过滤掉

适用: 列表筛选项、搜索表单、任何「按条件带参」的接口。


3. 多行字符串、拼文案(模板字符串天然支持换行)

场景: 弹窗文案、邮件正文、多行提示。

javascript 复制代码
const userName = '李四';
const count = 3;

const message = `尊敬的 ${userName}:
您有 ${count} 条待处理消息,请及时查看。`;
// 换行、变量都保留,不用 \n 和 + 拼

三、split / join 的常见用法

场景:?id=1&name=test 得到 { id: '1', name: 'test' }

javascript 复制代码
const search = '?id=1&name=test';

// 推荐:直接用 URLSearchParams 解析(和上面「拼」对应)
const params = Object.fromEntries(new URLSearchParams(search));
// { id: '1', name: 'test' }

// 若不能用地道 API,再用 split
const params2 = search
  .replace(/^\?/, '')
  .split('&')
  .reduce((acc, pair) => {
    const [key, value] = pair.split('=');
    acc[decodeURIComponent(key)] = decodeURIComponent(value ?? '');
    return acc;
  }, {});

注意: 值里可能带 =,所以「按第一个 = 拆」更稳,这里用 split('=') 只适合简单 value;复杂 query 建议统一用 URLSearchParams


2. 把「逗号分隔的 id」拆成数组,再拼回去(split + join)

场景: 接口返回 ids: "1,2,3",要转成数组处理;提交时再拼成 "1,2,3"

javascript 复制代码
const idsStr = '1,2,3';

const ids = idsStr.split(',').map((id) => id.trim()).filter(Boolean);
// ['1', '2', '3']

// 提交时再拼回去
const idsStrAgain = ids.join(',');
// '1,2,3'

注意: split(',') 后习惯加 .map(s => s.trim()).filter(Boolean),避免空串和前后空格。


3. 按换行拆成数组(split('\n'))

场景: 用户输入多行标签、多行关键词,一行一个。

javascript 复制代码
const input = '  tag1  \ntag2\n  tag3  ';
const tags = input.split('\n').map((s) => s.trim()).filter(Boolean);
// ['tag1', 'tag2', 'tag3']

四、正则的 80% 用法(小白友好版:从基础到实战)

先搞懂:正则的 "基础积木"(小白版) 先记住这几个最常用的符号,就像搭积木一样,组合起来就能实现大部分匹配 / 替换需求:

符号 / 语法 小白版解释 举例子
/内容/ 正则的 "容器",所有匹配规则都写在两个/之间 /abc/ 表示匹配字符串里的 abc
/内容/g g = global(全局),表示匹配所有符合规则的内容,不是只匹配第一个 'aaa'.replace(/a/g, 'b')bbb(不加 g 只替换第一个 a,变成 baa
\w 匹配「字母、数字、下划线」(简单记:匹配 "单词字符") /\w+/能匹配 name123order_001
\d 匹配「单个数字」(0-9) /\d/匹配 5/\d\d/ 匹配88
+ 表示 "前面的规则至少出现 1 次" /\d+/ 匹配 1 个或多个数字(比如 1123
* 表示 "前面的规则出现 0 次或多次"(用得少,优先记+ /\d*/ 能匹配空字符串1123
{n} 表示 "前面的规则正好出现 n 次" /\d{10}/匹配正好 10 个数字
^ 匹配 "字符串的开头"(锚定开头) /^1/只匹配以 1开头的字符串(比如 1380000 能匹配,a138 不能)
$ 匹配 "字符串的结尾"(锚定结尾) /\d$/ 只匹配以数字结尾的字符串
[^>] [] 表示 "匹配其中任意一个字符",^ [] 里表示 "排除" /[^>]+/匹配 "除了 > 之外的任意字符,至少 1 个"
() 捕获组:把匹配到的内容 "抓出来",后续能用到 /\{(\w+)\}/ 里的 (\w+) 会把 {name} 里的 name 抓出来
有没有同学看不懂 /\{(\w+)\}/ 的?

看这里:

  • \ 是转义符:正则里想匹配 {} / [] / () 等特殊符号本身时,必须加\
  • /\{(\w+)\}/ 的核心是匹配 {xxx} 格式的字符串,其中:
    • \{ / \} 匹配普通的{}
    • (\w+) 抓出 {} 中间的字母 / 数字 / 下划线(比如 name);
  • 新手写正则时,只要想匹配 "特殊符号本身",先加 \ 转义,就不会出错。

用法 1:占位符替换(把 {name} 换成真实值)

场景:服务端返回模板 " 您好,{name},您的订单{orderId}已发货 ",前端替换成当前用户和订单。 步骤拆解(小白能懂):

1. 规则/\{(\w+)\}/g 解析:

  • \{:匹配左大括号 {(因为 { 是正则特殊符号,要加\ 转义,告诉正则 "这就是普通的 {");
  • (\w+):捕获组,匹配字母 / 数字 / 下划线(比如 nameorderId),并把匹配结果存起来;
  • \}:匹配右大括号 }
  • g:全局匹配,把所有 {xxx} 都找出来。

2. replace 回调函数:(_, key) => data[key] ?? ''

  • 第一个参数 _:表示整个匹配的内容(比如 {name}),用不到就用 _ 占位;
  • 第二个参数 key:就是捕获组 (\w+) 抓到的内容(比如 name);
  • data[key] ?? '':从 data 里取对应的值,没有就用空串填充。
javascript 复制代码
const template = '您好,{name},您的订单{orderId}已发货';
const data = { name: '王五', orderId: 'ORD001' };

// 核心代码
const result = template.replace(/\{(\w+)\}/g, (_, key) => data[key] ?? '');
console.log(result); // 输出:'您好,王五,您的订单ORD001已发货'

// 小白试错:如果不加g,只会替换第一个占位符
const badResult = template.replace(/\{(\w+)\}/, (_, key) => data[key] ?? '');
console.log(badResult); // 输出:'您好,王五,您的订单{orderId}已发货'

用法 2:富文本简单处理:去掉 HTML 标签只留纯文本

**场景:**列表摘要只展示纯文本,需要把 <p>xxx</p> 里的 xxx 拿出来,或去掉所有标签。 规则 /<[^>]+>/g 解析

  • <:匹配左尖括号;
  • [^>]+:匹配 "除了>之外的任意字符,至少 1 个"(比如 pstrongdiv class="title");
  • >:匹配右尖括号;
  • g:全局替换,把所有标签都去掉。
javascript 复制代码
const html = '<p>这是一段<strong>加粗</strong>的文字&nbsp;还有空格</p>';

// 第一步:去掉所有HTML标签
const textWithoutTag = html.replace(/<[^>]+>/g, '');
console.log(textWithoutTag); // 输出:'这是一段加粗的文字&nbsp;还有空格'

// 第二步:还原常见的HTML实体(比如&nbsp;换成空格)
const text = textWithoutTag
  .replace(/&nbsp;/g, ' ')  // 空格实体转空格
  .replace(/&lt;/g, '<')    // < 实体转 <
  .replace(/&gt;/g, '>');   // > 实体转 >
console.log(text); // 输出:'这是一段加粗的文字 还有空格'

⚠️ 重要提醒 :这个规则只适合「简单、可控」的富文本(比如自己系统生成的短文本)。如果是复杂 HTML(比如带注释、<script>标签、属性里有>的),正则会失效,建议用 DOM 或专业库(如 cheerio)处理。

用法 3:富文本简单处理:限制摘要长度(截断 + 省略号)

场景 :列表里摘要最多显示 20 个字符,超出用 ...。 (先去标签再截断,避免截到标签中间,比如把<p>这是一段很长的文字</p>截成 <p>这是一段很长的文,导致标签不闭合)

javascript 复制代码
// 封装成通用函数,小白直接用
const getSummary = (html, maxLen = 20) => {
  // 第一步:先去标签和还原实体
  const pureText = html
    .replace(/<[^>]+>/g, '')
    .replace(/&nbsp;/g, ' ')
    .replace(/&lt;/g, '<')
    .replace(/&gt;/g, '>');
  // 第二步:判断长度,截断加省略号
  if (pureText.length > maxLen) {
    return pureText.slice(0, maxLen) + '...';
  }
  return pureText;
};

// 测试
const longHtml = '<div>这是一段非常非常长的富文本内容,需要截断显示</div>';
console.log(getSummary(longHtml, 10)); // 输出:'这是一段非常非常长...'

用法 4:简单格式校验(手机号、纯数字)

场景 :表单里「手机号」「纯数字」的简单校验,用 正则.test(要校验的字符串) ,返回 true/false

1. 手机号校验

规则 /^1\d{10}$/ 解析:

  • ^:字符串开头;
  • 1:第一个字符必须是 1(手机号开头都是 1);
  • \d{10}:后面跟正好 10 个数字;
  • $:字符串结尾; → 整体表示:整个字符串必须是 "1 + 10 个数字",长度正好 11 位。
javascript 复制代码
// 封装手机号校验函数
const isPhoneValid = (phone) => {
  // 先排除空值、非字符串情况
  if (!phone || typeof phone !== 'string') return false;
  return /^1\d{10}$/.test(phone);
};

// 测试
console.log(isPhoneValid('13800138000')); // true(正确手机号)
console.log(isPhoneValid('1380013800'));  // false(只有10位)
console.log(isPhoneValid('12345678901')); // false(开头不是1)
console.log(isPhoneValid('1380013800a')); // false(包含字母)

2. 纯数字校验

规则 /^1\d{10}$/ 解析:

  • ^:开头;
  • \d+:至少 1 个数字;
  • \d{10}:后面跟正好 10 个数字;
  • $:结尾; → 整体表示:整个字符串只能是数字,不能有其他字符,且不能为空。
javascript 复制代码
// 封装纯数字校验函数
const isPureNumber = (str) => {
  if (!str) return false; // 空串返回false
  return /^\d+$/.test(str);
};

// 测试
console.log(isPureNumber('12345')); // true
console.log(isPureNumber('123a5')); // false(含字母)
console.log(isPureNumber(''));      // false(空串)
console.log(isPureNumber('0'));     // true(单个0也符合)

用法总结

  1. 正则小白不用记所有语法,先掌握 /内容/g\w/\d+/{n}^/$() 这几个核心符号,就能搞定大部分场景;
  2. 正则的核心用法分 3 类:替换(replace)、校验(test)、提取(match),其中替换和校验是日常用得最多的;
  3. 写正则时,先拆解 "要匹配什么 / 排除什么",再用基础符号组合,优先加 g(全局)、^/``$`(整串匹配)避免漏匹配 / 错匹配;
  4. 复杂 HTML 处理别用正则,优先用 DOM 或专业库,正则只适合简单片段。

五、容易踩的坑

1. 模板字符串里要算表达式,用 ${} 包起来

javascript 复制代码
const a = 1, b = 2;
const wrong = `${a} + ${b} = a + b`;   // '1 + 2 = a + b'
const right = `${a} + ${b} = ${a + b}`; // '1 + 2 = 3'

2. query 里的中文、空格、特殊字符必须编码

javascript 复制代码
const name = '张 三';
const bad = `/api?name=${name}`;  // 空格和中文会破坏 URL
const good = `/api?name=${encodeURIComponent(name)}`;
// 或统一用 URLSearchParams

3. split 不传参时按每个字符拆

javascript 复制代码
'abc'.split();   // ['abc']
'abc'.split(''); // ['a','b','c']

要按「分隔符」拆就明确传参,例如 split(',')split('\n')


4. 空字符串 split 得到的是 ['']

javascript 复制代码
''.split(',');   // ['']
''.split(',').filter(Boolean); // []

拼 query、拼列表前若可能为空,先判断或 filter(Boolean),避免出现 ?key= 或末尾多余逗号。


5. 正则「去标签」不能覆盖所有 HTML 情况

javascript 复制代码
// 像 <div class="a"> 这种可以匹配
// 但 <script>...</script>、注释、属性里的 > 等,正则容易出错

仅用于「自己能控制的、结构简单的」富文本片段;其它用 DOM 或专业库。

六、实战推荐写法模板

接口 GET 参数拼接(带空值过滤):

javascript 复制代码
const baseUrl = '/api/list';
const params = { keyword: '...', page: 1, pageSize: 10, status: '' };
const query = new URLSearchParams(
  Object.fromEntries(
    Object.entries(params).filter(([_, v]) => v != null && String(v).trim() !== '')
  )
).toString();
const url = query ? `${baseUrl}?${query}` : baseUrl;

从当前页 search 取参数:

javascript 复制代码
const params = Object.fromEntries(new URLSearchParams(location.search));
const keyword = params.keyword ?? '';

逗号分隔字符串 ↔ 数组:

javascript 复制代码
const toIds = (s) => (s ?? '').split(',').map((id) => id.trim()).filter(Boolean);
const toStr = (arr) => (arr ?? []).filter(Boolean).join(',');

简单占位符替换:

javascript 复制代码
const fillTemplate = (template, data) =>
  template.replace(/\{(\w+)\}/g, (_, key) => data[key] ?? '');

富文本摘要(去标签 + 截断):

javascript 复制代码
const toSummary = (html, maxLen = 20) => {
  const text = html.replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ');
  return text.length > maxLen ? text.slice(0, maxLen) + '...' : text;
};

七、小结

场景 推荐写法
拼 URL、拼文案、多行字符串 模板字符串 ${base}?${query}
拼/解析 query URLSearchParams + 模板字符串 或 split/reduce
有值才带参 filterURLSearchParams,再拼到 URL
逗号/换行拆成数组 split(',') / split('\n') + trim + filter(Boolean)
数组拼成字符串 join(',')
占位符替换 {key} replace(/\{(\w+)\}/g, (_, key) => data[key])
简单去 HTML 标签 replace(/<[^>]+>/g, '')(仅简单片段)
摘要截断 先去标签再 slice(0, len) + '...'
简单格式校验 /^1\d{10}$/.test(phone)

记住:拼用模板字符串 + URLSearchParams,拆用 split/URLSearchParams,替换/匹配用正则。日常写接口参数、搜索条件、简单富文本时,先想清楚是「拼、拆、还是替换/校验」,再选对应方式,代码会清晰很多,也少踩编码和空值的坑。

特别提醒:

  • query 里的中文和特殊字符一定要编码(URLSearchParamsencodeURIComponent)。
  • 空数组/空字符串在 split/join 时要考虑 filter(Boolean) 和「是否带问号」。
  • 正则只用于简单、可控的富文本;复杂 HTML 用 DOM 或专门库。

以上就是本次的学习分享,欢迎大家在评论区讨论指正,与大家共勉。

我是 Eugene,你的电子学友。

如果文章对你有帮助,别忘了点赞、收藏、加关注,你的认可是我持续输出的最大动力~

相关推荐
不会敲代码11 小时前
React组件通信实战:从Todo应用彻底搞懂父子、子父、兄弟通信
前端·react.js
wuhen_n1 小时前
前端构建工具:从Rollup到Vite
前端
钟智强1 小时前
深度剖析CVE-2023-41064与CVE-2023-4863:libwebp堆溢出漏洞的技术解剖与PoC构建实录
前端·后端
钟智强1 小时前
MySQL客户端惊现高危漏洞CVE-2023-21980,可导致远程代码执行
前端·后端
Cache技术分享1 小时前
332. Java Stream API - Java Stream 实战进阶:按年份找出合作最多的作者对
前端·后端
SuperEugene1 小时前
前端正则表达式完全指南:从手写不出到随手就来
前端·正则表达式
Highcharts.js1 小时前
图表学习|基于highcharts创建子弹图表,以及子弹图的应用与扩展设计
javascript·信息可视化·highcharts·图表开发·子弹图表·kpi图
九狼1 小时前
Flutter Riverpod + MVI 状态管理实现的提示词优化器
前端·flutter·github
巴巴博一2 小时前
【前端架构实战】拒绝切 Tab 白屏!纯手写 Vue/uni-app 多标签页“零延迟缓存”列表架构
前端·vue.js·架构