实现千分位格式化、模板字符串渲染和 Cookie 解析。
先理解原理和示例,再练习完整口述与追问。
回答要点
千分位:先用正则拆出符号、整数与小数部分,只对整数部分用 \B(?=(\d{3})+(?!\d)) 插入逗号;业务中优先 Intl.NumberFormat。模板渲染:正则匹配 {{ path }},按点路径从数据中取值,只读取自有属性,缺失时保留占位符,null 渲染为空字符串。Cookie 解析:按分号拆分,按第一个等号切分键值,同名取第一个,解码失败保留原值。
原理拆解
\B 匹配非单词边界,确保不在数字开头插入逗号;先行断言 (?=(\d{3})+(?!\d)) 要求后面的数字个数是 3 的倍数。如果对整个字符串(含小数)应用这个正则,小数部分也会被插入逗号,所以必须拆开处理。科学计数法、NaN 等无法匹配的输入直接抛错。
模板取值时,如果允许读取原型链,{{ constructor }} 或 {{ __proto__ }} 会暴露内部对象,所以只读自有属性。渲染结果插入 HTML 前还需要转义,这里只负责字符串替换。
Cookie 值本身可能包含等号(Base64),所以只按第一个等号切分。浏览器发送的 Cookie 中,Path 更具体的同名 Cookie 排在前面,通常取第一个。用 Object.create(null) 作为结果对象,避免名为 __proto__ 的 Cookie 修改原型。
示例与推演
function formatThousands(value) {
const match = /^(-?)(\d+)(\.\d+)?$/.exec(String(value))
if (!match) throw new TypeError(`无法格式化:${value}`)
const [, sign, integer, fraction = ''] = match
return sign + integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + fraction.replace(/\.?0+$/, '')
}
function render(template, data) {
return template.replace(/\{\{\s*([\w.]+)\s*\}\}/g, (placeholder, path) => {
let value = data
for (const key of path.split('.')) {
if (value == null || !Object.prototype.hasOwnProperty.call(Object(value), key)) return placeholder
value = value[key]
}
return value == null ? '' : String(value)
})
}
function parseCookie(cookieString) {
const result = Object.create(null)
for (const part of cookieString.split(';')) {
const index = part.indexOf('=')
if (index < 0) continue
const name = part.slice(0, index).trim()
if (!name || name in result) continue
let value = part.slice(index + 1).trim()
if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) value = value.slice(1, -1)
try {
value = decodeURIComponent(value)
} catch {
// 保留无法解码的原始值
}
result[name] = value
}
return result
}
推演:formatThousands('-1234567.50') 得到 '-1,234,567.5',末尾的 0 被去掉,'1000.00' 得到 '1,000';render('你好,{{ user.name }},{{ missing }}', { user: { name: 'Ada' } }) 得到 '你好,Ada,{{ missing }}';parseCookie('token=a=b; theme=dark; token=old') 中 token 为 'a=b'。
易错点
金额展示若要求固定两位小数,不应去掉末尾的 0,应使用 Intl.NumberFormat 的 minimumFractionDigits;decodeURIComponent 遇到不完整的百分号编码会抛 URIError,不捕获会让整个解析失败。
参考回答可直接练习口述
千分位先拆出符号、整数和小数,只对整数部分用非单词边界加先行断言的正则插入逗号,业务里更推荐 Intl.NumberFormat。模板渲染用正则匹配双花括号里的路径,逐级读取自有属性,缺失时保留占位符,null 渲染为空,插入 HTML 前还要转义。Cookie 解析按分号拆分、按第一个等号切分键值,同名取第一个,用无原型对象存结果,解码失败保留原值。