ejs模板引擎实现原理

const fs = require("fs");
const path = require("path");
let template = fs.readFileSync(path.resolve(__dirname,"./views/index.html"),"utf-8");

let obj = {
    arr:["a","b","c"]
}

function render(temp,data){
  /*
   * with(obj){}
   * with将表达式作用域内的指针指向obj
   *
   */
  // 拼接字符串str变量,包含在with作用域内,可以让执行后的字符串this指针指向data
  let head = "with(data){\r\n let str = `"
  // 转换<%= %>
  let content = temp.replace(/<%=([\s\S]*?)%>/g, function () {
    return "${" + arguments[1] + "}"
  })
  // 转换<%  %>,完成后继续拼接字符串
  content = content.replace(/<%([\s\S]*?)%>/g, function () {
    return "`\r\n" + arguments[1] + "\r\n str+=`"
  })
  // 拼接结束
  let tail = "`\r\n return str \r\n}"
  // 执行函数,好处可以传参
  let fn = new Function("data", head + content + tail)

  return fn(data)
};

let str = render(template,obj);

console.log(str.toString());