js-challenges
js-challenges copied to clipboard
正则表达式模版字符串
String.prototype.render = function (data) {
return this.replace(/{{[.\s\S]*?}}/g, match => {
if ((match = match.substring(2, match.length - 2).trim()) == "") {
return "";
} else if (match.startsWith("#")) {
return eval(match.substr(1, match.length - 1));
} else {
return data[match] ? data[match] : "";
}
})
}
const data = {
name: "小明",
age: 16,
school: "第三中学",
classroom: "教室2"
}
console.log(
"{{ name }} 今年 {{ age }} 岁,就读于 {{ school }} 今天在 {{ classroom }} 上课,{{ name }} {{ #data.age >= 18 ? '成年了' : '未成年' }}".render(data)
);
// 小明 今年 16 岁,就读于 第三中学 今天在 教室2 上课,小明 未成年
console.log(
`{{name}}说了句{{#
if (data.age >= 18) {
"我已经成年了!"
} else {
"我还没有成年!"
}
}}`.render(data)
);
// 小明说了句我还没有成年!
function createTemplate(template = '', option = {}) {
const { dynamic = ['{{', '}}'], statement = '#' } = option
const RE_CONTENT = '[.\\s\\S]*'
const RE_DYNAMIC = new RegExp(
`(${RE_CONTENT}?)${dynamic[0]}(${RE_CONTENT}?)${dynamic[1]}(${RE_CONTENT})`
)
const tokens = []
const createTokens = (tpl) => {
const match = tpl.match(RE_DYNAMIC)
if (match) {
// ['', text, dynamic, nexTemplate] = match
match[1] && tokens.push({
type: 'text',
content: match[1],
})
const dynamicMatch = match[2].trim()
dynamicMatch && tokens.push({
type: dynamicMatch.startsWith(statement) ? 'statement' : 'dynamic',
content: dynamicMatch,
});
match[3] && createTokens(match[3])
} else {
tokens.push({
type: 'text',
content: tpl,
})
}
}
createTokens(template)
return function format(data) {
return tokens.map(({ type, content }) => {
switch (type) {
case 'text':
return content
case 'dynamic':
return data[content]
case 'statement':
const fn = new Function(...Object.keys(data), content.slice(1))
return fn(...Object.values(data))
}
}).join('')
}
}
const template = createTemplate(`
名字: {{ name }}
{{}}
年龄: {{ age }}
{{#
if (age > 18) {
return '成年人'
} else {
return '未成年人'
}
}}
`)
console.log(template({ name: "张三", age: 14 }))
console.log(template({ name: "李四", age: 19 }))
补一个双指针的写法,效率可能高一点。
好奇题目的模板字符串的含义,不应该是 es6 标准的${}
这种字符串吗?
const data = {
name: "小明",
age: 16,
school: "第三中学",
classroom: "教室2",
};
// 解构取值
let { name, age, school, classroom } = data;
/**
* @description: 双指针匹配 模板字符串,发现${}
* @param {*} s
* @return {*}
* @author: jlx
*/
function matchStrV2(s) {
let res = "";
for (let i = 0; i < s.length - 1; i++) {
let j = i + 2;
if (s[i] == "$" && s[i + 1] == "{") {
// 直到 右侧括号匹配成功
while (j < s.length && s[j] != "}") j++;
// 说明匹配成功
if (s[j] == "}") {
res += eval(s.substring(i + 2, j));
}
i = j + 1;
} else {
res += s[i];
}
}
return res;
}
let cases =
"${ name } 今年 ${ age } 岁,就读于 ${ school } 今天在 ${ classroom } 上课,${ name } ${ data.age >= 18 ? '成年了' : '未成年' }";
console.log(matchStrV2(cases));
// 小明今年 16岁,就读于 第三中学今天在 教室2上课,小明未成年
// 如果是es6标准的模板字符串``,第二个case好像是非法的
String.prototype.render = function (data) { return this.replace(/{{[.\s\S]*?}}/g, match => { if ((match = match.substring(2, match.length - 2).trim()) == "") { return ""; } else if (match.startsWith("#")) { return eval(match.substr(1, match.length - 1)); } else { return data[match] ? data[match] : ""; } }) } const data = { name: "小明", age: 16, school: "第三中学", classroom: "教室2" } console.log( "{{ name }} 今年 {{ age }} 岁,就读于 {{ school }} 今天在 {{ classroom }} 上课,{{ name }} {{ #data.age >= 18 ? '成年了' : '未成年' }}".render(data) ); // 小明 今年 16 岁,就读于 第三中学 今天在 教室2 上课,小明 未成年 console.log( `{{name}}说了句{{# if (data.age >= 18) { "我已经成年了!" } else { "我还没有成年!" } }}`.render(data) ); // 小明说了句我还没有成年!
面试会考正则吗,完全不会
function renderTemplate(template, data) {
const regex = /{{(.*?)}}/g;
return template.replace(regex, (match, key) => {
if (key.startsWith("#")) {
return eval(key.substr(1));
} else {
return data[key.trim()] || "";
}
});
}
/**
*遇到#表示是表达式
*遇到字符表示变量
*/
String.prototype.render = function (data) {
return this.replace(/{{[\s\S]*?}}/g, match => {
match = match.slice(2, match.length - 2).trim();
// console.log(match)
if (match == "") {
return;
} else if (match[0] == '#') {
return eval(match.slice(1));
} else {
return data[match] || '';
}
})
}
const data = {
name: "小明",
age: 16,
school: "第三中学",
classroom: "教室2"
}
console.log(
"{{ name }} 今年 {{ age }} 岁,就读于 {{ school }} 今天在 {{ classroom }} 上课,{{ name }} {{ #data.age >= 18 ? '成年了' : '未成年' }}".render(data)
);
// 小明 今年 16 岁,就读于 第三中学 今天在 教室2 上课,小明 未成年
console.log(
`{{name}}说了句{{#
if (data.age >= 18) {
"我已经成年了!"
} else {
"我还没有成年!"
}
}}`.render(data)
);
// 小明说了句我还没有成年!
索性把正则写完整一些,少一些字符串操作吧
function resolveStr(tpl, model) {
const reg = /{{\s*(.+?)\s*}}/g
return tpl.replace(reg, (str, key) => {
if (key.startsWith('#')) {
key = key.slice(1)
return eval(key)
}
console.log(str, key)
return eval(`model.${key}`)
})
}
String.prototype.render = function (data) {
return this.replace(/{{\s*([\S\s]*?)\s*}}/g, (match, p1) => {
if (p1 && p1[0] === '#') return eval(p1.slice(1))
else return data[p1] || ''
})
}
'{{1}}222{{3}}'.replace(/({{\w*}})/g,m => {
console.log(m)
})
'{{1}}222{{3}}'.replace(/({{\w*}})/g,m => { console.log(m) })
没懂题目啥意思 单纯匹配模板字符串?