直接上题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
实现将字符串中的特定字符串替换为obj的对应属性
*/
var greeting = 'My name is ${name}, age ${age}, I am a ${job.jobName}';
var employee = {
name: 'XiaoMing',
age: 11,
job: {
jobName: 'designer',
jobLevel: 'senior'
}
};
var result = greeting.render(employee);
console.log(result);// My name is XiaoMing,age 11, I am a designer

解决方案一:采用正则表达式

1
2
3
4
5
6
7
String.prototype.render = function (obj){
return this.replace(/\$\{(\w+|\w+\.\w+)\}/g, match => {
var keys = match.replace("${", "").replace("}", "").split(".");
var result = keys.reduce((acc, cv) => acc[cv], obj);
return result === undefined ? match : result; //如果存在指定的属性则替换,否则不替换
})
}

reduce()方法对累加器和数组中的每个元素从左至右应用一个函数,将其减少为单个值。

关于reduce()方法,看这里

解决方案二:采用ES6字符串模板

1
2
3
4
5
6
7
8
9
String.prototype.render = function (obj) {
//ES6解构、对象keys方法、在函数内部解构并自动展开变量
eval(`var {${Object.keys(obj).join(",")}} = obj`);
//利用eval使字符串直接作为ES6解析
return eval("`" + this + "`");
}
/*
将最外层对象去掉,使用解构赋值将属性和属性值作为单独的变量存在,然后再使用字符串模板,这样就能在作用域中找到模板中${}中字符串对应的变量,从而完成模板渲染。
*/

解构赋值看这里,ES6字符串模板看这里

解决方法三:with()方法

1
2
3
4
5
String.prototype.render = function (obj) {
with(obj) {
return eval("`" + this + "`");
}
}

with()语句的作用是扩展作用域链。(当然已经不推荐使用with()方法了)

关于with方法,可以看这里