- 教程
- 文档
【免费下载链接】30-seconds-of-code
Coding articles to level up your development skills
3 位十六进制颜色码(如#03f)是 6 位颜色码(#0033ff)的简写形式,在 CSS 与日常前端开发中十分常见。本文以 30 seconds of code 仓库中的 extend-hex.md 为骨架,完整讲解其背后的逐字符重复原理、完整可运行的extendHex实现,并结合仓库内颜色转换系列文章剖析该技巧在真实代码中的复用价值。读完本文,你将掌握如何用String.prototype.slice()、String.prototype.split()、Array.prototype.map()与Array.prototype.join()的组合,在几行代码内稳健完成 3 位到 6 位颜色码的转换,并了解其边界情况与适用前提。
为什么需要扩展 3 位十六进制颜色码
十六进制颜色码是 Web 开发中最常用的颜色表示方式。标准形式为6 位十六进制数,红、绿、蓝三个分量各占 2 位,例如#ff0000表示纯红色。为了节省书写成本,CSS 允许在满足条件时使用3 位简写:每一位数字都会被浏览器自动重复一次,从而还原成完整的 6 位码。例如:
#03f→ 展开为#0033ff#f00→ 展开为#ff0000#abc→ 展开为#aabbcc
这种简写形式非常普遍,但在程序化处理颜色时却会带来麻烦:很多解析逻辑、颜色转换工具或数据归一化流程要求输入必须是固定长度的 6 位码。因此,在把这些 3 位码交给下游处理之前,常常需要先把它们转换回完整的6 位形式。
核心原理:逐字符重复
3 位码转换为 6 位码,本质上只是一个非常简单的规则——把 3 位码中的每一位字符重复一次,拼接到一起即可。以#03f为例:
- 去掉可选的
#前缀,得到03f; - 逐字符重复:
0→00,3→33,f→ff; - 拼接结果:
0033ff; - 补回
#前缀:#0033ff。
由于每一位的重复是相互独立的,这个转换可以用数组方法优雅地表达:先用split('')把字符串拆成字符数组,再用map()让每个字符自己和自己拼接,最后用join('')把结果粘回字符串。
完整实现:extendHex
在 30 seconds of code 的 extend-hex.md 中,给出了如下完整实现:
const extendHex = shortHex => '#' + shortHex .slice(shortHex.startsWith('#') ? 1 : 0) .split('') .map(x => x + x) .join(''); extendHex('#03f'); // '#0033ff' extendHex('05a'); // '#0055aa'这个实现高度简洁,逻辑全部通过方法链完成。下面分步拆解每一环的职责:
1. 处理可选的#前缀
输入字符串可能带#(如#03f),也可能不带(如03f)。为了统一后续处理,需要先移除可能存在的#。这里用String.prototype.startsWith()判断前缀是否存在,再通过String.prototype.slice()决定从第1个字符还是第0个字符开始截取:
shortHex.slice(shortHex.startsWith('#') ? 1 : 0)- 输入
#03f→ 从索引1开始,得到03f; - 输入
05a→ 从索引0开始,得到05a。
这样extendHex对两种常见输入格式都能正确工作,这正是示例中两个调用点分别覆盖两种形式的原因。
2. 拆分为字符数组
String.prototype.split('')把去除前缀后的字符串按每个字符拆分成数组:
'03f'.split(''); // ['0', '3', 'f']3. 逐字符重复
Array.prototype.map()遍历数组,对每个字符执行x + x的字符串拼接,实现“自己重复自己”:
['0', '3', 'f'].map(x => x + x); // ['00', '33', 'ff']4. 拼接并补回前缀
Array.prototype.join('')把重复后的字符片段拼回一个字符串,再在最前面拼接'#':
'#' + ['00', '33', 'ff'].join(''); // '#0033ff'输入前提与边界情况说明
从实现结构看,extendHex假定输入本身就是合法的3 位十六进制码(0-9、a-f),它只负责“扩展长度”,不负责“校验合法性”。因此需要注意:
- 若传入的不是 3 位十六进制码,结果不会按预期生成;例如传入
#1234会得到#11223344(长度错误的结果),传入#xyz会得到#xxyyzz; - 若确有校验需求,可在调用
extendHex之前用正则(如/^#?([0-9a-f]{3})$/i)验证输入,再将匹配结果传入转换逻辑; - 该方法同样可以处理带大写字母的输入(如
#FFF→#FFFFFF),因为重复操作对大小写不敏感,最终输出保留输入原本的大小写形式。
该技巧在仓库中的关联应用
3 位码扩展是颜色转换链路的前置步骤
在仓库的 rgb-hex-hsl-hsb-color-format-conversion.md 中,hexToRgb函数在提取 RGB 分量之前,必须先处理 3 位简写的情况——它用了一模一样的逐字符重复思路:
if (h.length === 3) h = [...h].map(x => x + x).join('');区别仅在于这里用展开运算符[...h]取代了split('')(两者效果等价),并同时通过slice(hex.startsWith('#') ? 1 : 0)处理#前缀。这印证了 3 位到 6 位的扩展是十六进制颜色解析链路中通用的前置归一化步骤,本文的extendHex正是把它抽象成了独立可复用的工具函数。
它是 JavaScript 颜色工具集的组成部分
该片段被收录在 content/collections/js/colors.yaml 的js/colors集合中,与random-hex-color-code、rgb-hex-hsl-hsb-color-format-conversion等片段共同构成仓库内 JavaScript 颜色处理工具集。该集合在 colors.yaml 中被描述为“从生成随机颜色码到在 hex 与 RGB 之间转换,甚至用 HSL 调整颜色亮度”的一系列文章,而extendHex作为其中处理简写颜色码的专属片段,负责补齐 3 位码这一常见输入形态。
与相邻工具的互补关系
- random-hex-color-code.md 生成随机 6 位颜色码时,用
String.prototype.slice(0, 6)截取前 6 个字符——与extendHex的“扩展”方向相反,一个保证长度上限、一个保证长度下限; - rgb-hex-hsl-hsb-color-format-conversion.md 中的
hexToRgb内部复用 3 位扩展逻辑后再做位运算解析分量; - decimal-to-hex.md 展示了用
Number.prototype.toString(16)与parseInt(hex, 16)在十进制与十六进制数字间往返,可作为理解十六进制字符串本质(即 16 进制数字串)的基础。
三者与extendHex一起,覆盖了十六进制颜色码生成、扩展、解析与格式转换的完整闭环。
小结
extendHex用一行方法链解决了 3 位十六进制颜色码到 6 位码的转换:slice()处理可选前缀、split()拆字符、map()逐位重复、join()还原字符串。它逻辑清晰、无副作用,适合作为颜色归一化工具直接落地使用,也是理解字符串与数组方法链式组合的典型教学案例。使用时只需注意其“扩展而非校验”的定位,对不可信输入先行校验即可。
- 教程
- 文档
【免费下载链接】30-seconds-of-code
Coding articles to level up your development skills
相关推荐
30 seconds of code:JavaScript 十进制与十六进制互转完整指南
30 seconds of code:JavaScript 十进制与十六进制互转完整指南 在 JavaScript 中,数字默认以十进制形式转换为字符串,但通过
教程文档CANN ops-math 算子开发指南:aclnnLog 与 aclnnInplaceLog 自然对数算子接口详解与实战
CANN ops math 算子开发指南:aclnnLog 与 aclnnInplaceLog 自然对数算子接口详解与实战 导读 本文基于 CANN ops m
教程文档30 seconds of code:用 JavaScript 精准调整 HSL 颜色亮度(changeLightness 实战解析)
30 seconds of code:用 JavaScript 精准调整 HSL 颜色亮度(changeLightness 实战解析) 本篇指南以 30 sec
教程文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考