# 实用-字符串模板解析

# 一、简单版

# 描述

实现一个 render(template, context) 方法,将 template 中的占位符用 context 填充。

不需要有控制流成分(如 循环、条件 等等),只要有变量替换功能即可 级联的变量也可以展开 被转义的的分隔符 { 和 } 不应该被渲染,分隔符与变量之间允许有空白字符

# 实现

function render(templateStr, context) {
    return templateStr.replace(/\$\{(.*?)\}/g, (match, key) => context[key.trim()]);
}

render("My name is ${name}, I'm ${age} years old.", {name: 'Aaron', age: 31})
// "My name is Aaron, I'm 31 years old."
1
2
3
4
5
6

# 二、复杂版

# 描述

实现函数使得将str字符串中的 {} 内的变量替换,如果属性不存在保持原样(比如 {a.d}

类似于模版字符串,但有一点出入,实际上原理大差不差

var a = {
	b: 123,
	c: '456',
	e: '789',
}
var str=`a{a.b}aa{a.c}aa {a.d}aaaa`;
// => 'a123aa456aa {a.d}aaaa'

1
2
3
4
5
6
7
8

# 实现

const fn1 = (str, obj) => {
	let res = '';
    // 标志位,标志前面是否有{
	let flag = false;
	let start;
	for (let i = 0; i < str.length; i++) {
		if (str[i] === '{') {
			flag = true;
			start = i + 1;
			continue;
		}
		if (!flag) res += str[i];
		else {
			if (str[i] === '}') {
				flag = false;
				res += match(str.slice(start, i), obj);
			}
		}
	}
	return res;
}
// 对象匹配操作
const match = (str, obj) => {
	const keys = str.split('.').slice(1);
	let index = 0;
	let o = obj;
	while (index < keys.length) {
		const key = keys[index];
		if (!o[key]) {
			return `{${str}}`;
		} else {
			o = o[key];
		}
		index++;
	}
	return o;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
上次更新: 1/5/2022, 9:25:14 AM