3 种实现 JavaScript 模板引擎的方法
、
英文 | https://javascript.plainenglish.io/interviewer-can-you-implement-a-javascript-template-engine-me-crap-fcd1dd6a3889
翻译 | 杨小爱
const template = 'My name is ${name}, age ${age}, I am a ${job.name}'const employee = { name: 'fatfish', age: 100, job: { name: 'front end development' }}const renderStr = template.render(employee)// What is the output string?console.log(renderStr) // 'My name is fatfish, age 100, I am a front end development'什么是模板引擎?
你一定用过nunjucks之类的模板引擎,题型和它的功能很像,请跟着我一起举个例子。
nunjucks.configure({ autoescape: true })const template = 'My name is {{name}}, age {{age}}, I am a {{job.name}}'const employee = { name: 'fatfish', age: 100, job: { name: 'front end development' }}const renderStr = nunjucks.renderString(template, employee)console.log(renderStr) // My name is fatfish, age 100, I am a front end development我可怜的朋友被要求实现这样的东西,它只是将 ${name} 替换为 {{name}} 而几乎没有别的。
解决方案 1:正则表达式
看到这个面试题,我的反应是用正则表达式来解决。只要我们能提取出字符串中的具体字符(name、age、job.name),问题就迎刃而解了。
第 1 步:提取变量
String.prototype.render = function (obj) { const template = this const variableRegex = /\$\{([^${}]+)\}/g template.replace(variableRegex, ($, variable) => { console.log(variable) })}const template = 'My name is ${name}, age ${age}, I am a ${job.name}'template.render()太好了,我们得到了 name、age、job.name 变量。下面我们来看看这个正则表达式是什么意思,可以点这个链接:https://jex.im/regulex/#!flags=&re=%5C%24%5C%7B(%5B%5E%24%7B%7D%5D%2B)%5C%7D进行查看。
const variableRegex = /\$\{([^${}]+)\}/g我们要关注 ([^${}]+),这意味着至少有一个除 $、{、} 之外的字符。
第二步:获取obj的具体值
当我们得到name, age, job.name,如何关联到employee?
String.prototype.render = function (obj) { const template = this const variableRegex = /\$\{([^${}]+)\}/g const getVariableValue = (variable) => { // [ 'name' ]、[ 'age' ]、[ 'job', 'name' ] variable = variable.split('.') let variableValue = obj // For example, if we want to get the value of job.name, we will go through the following steps // Initialization: variableValue = { name: 'fatfish', age: 100, job: { name: "front end development" } } // first loop: variableValue = { name: "front end development" } // Second loop: variableValue = 'front end development' // Third loop: finished, return 'front end development' while (variable.length) { variableValue = variableValue[ variable.shift() ] } return variableValue } const renderStr = template.replace(variableRegex, ($, variable) => { return getVariableValue(variable) }) return renderStr}
const template = 'My name is ${name}, age ${age}, I am a ${job.name}'const employee = { name: 'fatfish', age: 100, job: { name: 'front end development' }}const renderStr = template.render(employee)
console.log(renderStr)我们通过正则表达式实现了一个简单的模板引擎,请小伙伴们为自己打气。
解决方案 2:eval
朋友们,让我们回顾一下es6中模板字符串的基本用法。
const name = 'fatfish'const age = 100const job = { name: 'front end development'}const renderString = `My name is ${name}, age ${age}, I am a ${job.name}`
console.log(renderString)模板字符串非常有用,它们允许我们在字符串中嵌入表达式。
让我们再次学习如何使用 eval。
const employee = { name: 'fatfish', age: 100, job: { name: 'front end development' }}eval('var { name, age, job } = employee')
console.log(name, age, job)很神奇,就好像我们声明了三个变量name、age、job,我们可以随意打印出它们的值。
有了这两个知识点,我们的第二个方案就出来了。
String.prototype.render = function (obj) { const template = this // var { name, age, job } = obj eval(`var {${Object.keys(obj).join(',')}} = obj`) // `My name is ${name}, age ${age}, I am a ${job.name}` const renderStr = eval('`' + template + '`') return renderStr}const template = 'My name is ${name}, age ${age}, I am a ${job.name}'const employee = { name: 'fatfish', age: 100, job: { name: 'front end development' }}
const renderStr = template.render(employee)给自己鼓掌,因为你已经用两种方式实现了一个精简版模板引擎。
解决方案3:with
虽然我们很少用到with关键字,但是可以用来解决这个问题。
这段代码的输出是什么?
const employee = { name: 'fatfish', age: 100, job: { name: 'front end development' }}with (employee) { age, job)}这与上面的代码几乎具有相同的效果,但更加简洁易懂。
// var { name, age, job } = objeval(`var {${Object.keys(obj).join(',')}} = obj`)好吧,我想你已经猜到了答案。
String.prototype.render = function (obj) { with(obj) { return eval('`' + this + '`') }}const template = 'My name is ${name}, age ${age}, I am a ${job.name}'const employee = { name: 'fatfish', age: 100, job: { name: 'front end development' }}const renderStr = template.render(employee)
console.log(renderStr)后总结
以上就是我今天跟你分享的3种JavaScript模板引擎的实现方法,希望对你有帮助
相关文章