模板字符串的进阶玩法,你可能只用了它1%的功能
大家好,我是全栈老李。今天聊个看似简单但暗藏玄机的东西——模板字符串。很多人觉得它就是个高级版字符串拼接,那可就太小看ES6了。
你以为的${}
只是冰山一角
先看个最基础的用法,老司机们肯定都见过:
const name = '全栈老李';
console.log(`大家好,我是${
name}`); // 大家好,我是全栈老李
但如果你以为模板字符串就这点能耐,那就好比把iPhone当老人机用。下面这些骚操作才是重头戏。
进阶玩法一:带标签的模板字符串
先看这段代码,猜猜输出什么:
function leeTag(strings, ...values) {
console.log(strings); // ["吃了", "个包子", ""]
console.log(values); // [3, "韭菜"]
return '饱了';
}
const count = 3;
const type = '韭菜';
const result = leeTag`吃了${
count}个包子${
type}`;
console.log(result); // 输出什么?(全栈老李提示:注意返回值)
这个leeTag
就是个标签函数,它能拦截模板字符串的解析过程。strings
是静态文本部分(被变量插值分割后的数组),values
是动态插值部分。
真实应用场景:
国际化文案处理(动态插入多语言变量)
安全过滤(自动转义HTML标签防XSS)
样式组件(比如styled-components底层原理)
举个防XSS的例子:
function safeHtml(strings, ...values) {
let result = '';
strings.forEach((str, i) => {
result += str;
if (i < values.length) {
result += String(values[i])
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
}
});
return result;
}
const userInput = '<script>alert("嘿嘿")</script>';
const safeOutput = safeHtml`<div>${
userInput}</div>`;
// 输出:<div><script>alert("嘿嘿")</script></div>
(全栈老李小贴士:标签函数的第一个参数总有n+1
个元素,values
总有n
个元素)
进阶玩法二:嵌套模板与动态模板
模板字符串可以无限套娃:
const isVIP = true;
const discount = 0.8;
const priceTemplate =
`当前价格:¥${
100 * (isVIP ? discount : 1)}(${
isVIP ? '会员价' : '原价'})`;
// 更复杂的嵌套
const generateUI = (type) => {
const base = `
<div class="card">
${
type === 'premium'
? `<img src="gold-icon.png"/>`
: `<span>普通用户</span>`}
</div>
`;
return base;
};
冷知识:模板字符串的缩进会被保留,如果嫌弃换行符和空格,可以这样处理:
const sql = `
SELECT * FROM users
WHERE id = ${
id}
`.trim().replace(/s+/g, ' ');
进阶玩法三:与函数式编程的化学反应
配合高阶函数玩出花样:
const data = [
{
name: '张三', score: 85 },
{
name: '李四', score: 92 }
];
const createRow = ({
name, score}) => `
<tr>
<td>${
name}</td>
<td>${
score.toFixed(2)}</td>
<td>${
score >= 90 ? '优秀' : '良好'}</td>
</tr>
`;
const tableHtml = `
<table>
${
data.map(createRow).join('')}
</table>
`;
(全栈老李友情提示:array.map().join('')
是生成动态HTML的经典模式)
课后作业:实现一个模板引擎
来道面试真题练练手:
/**
* 实现一个简易模板引擎
* @param {string} template 模板字符串,如"Hello, {
{name}}!"
* @param {object} data 数据对象,如{name: 'World'}
* @return {string} 渲染后的字符串
* 示例:
* render("Hello, {
{name}}!", {name: '全栈老李'})
* 输出:"Hello, 全栈老李!"
*/
function render(template, data) {
// 你的代码写在这里
return result;
}
要求:
能处理{
格式的插值
{prop}}
处理不存在的属性时返回空字符串
禁止使用eval/new Function
在评论区留下你的答案,我会随机抽几位同学的代码进行点评。下期公布参考答案时,会分析几种典型实现方案的性能差异(包括正则优化技巧)。
我是全栈老李,我们下次见!
🔥 必看面试题
【初级】前端开发工程师面试100题(一)
【初级】前端开发工程师面试100题(二)
【初级】前端开发工程师的面试100题(速记版)
我是全栈老李,一个资深Coder!
写码不易,如果你觉得本文有收获,点赞 + 收藏走一波!感谢鼓励🌹🌹🌹
暂无评论内容