深入浅出node模板解析错误escape is not a function
操作
var escape = function (html) {
return String(html)
.replace(/&(?!\w+;)/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
}
var complie = function (str) {
console.log(str)
var tpl = str.replace(/<%=([\s\S]+?)%>/g, function (match, code) {
// 转义
return "' + escape(" + code + ") + '"
}).replace(/<%-([\s\S]+?)%>/g, function (match, code) {
// 正常输出
return "' + " + code + " + '"
}).replace(/<%([\s\S]+?)%>/g, function (match, code) {
return "';\n" + code + "\n tpl += '"
}).replace(/\'\n/g, '\'')
.replace(/\n\'/gm, '\'')
console.log('----------代码替换模板----------')
console.log(tpl)
tpl = "tpl = '" + tpl + "'"
tpl = tpl.replace(/''/g, '\'\\n\'')
tpl = ' var tpl = ""\n with (obj || {}) {\n ' + tpl + '\n }\n return tpl'
return new Function('obj', 'escape', tpl)
}
var render = function(complie, data) {
console.log('----------构造函数----------')
console.log(complie.toString())
console.log('----------运行函数----------')
return complie(data)
}
var tpl = [
'<% if (obj.user) { %>',
'<h2><%=user.name%></h2>',
'<% } else { %>',
'<h2>匿名用户</h2>',
'<% } %>'].join('\n')
console.log('----------模板----------')
console.log(tpl)
console.log(render(complie(tpl), {user: {name: 'Jackson Tian'}}))
//console.log('\n\n')
//console.log(render(complie(tpl), {}))
异常信息
TypeError: escape is not a function
at eval(eval at complie (F:\workspace\javascript workspace\plNode\prj8_5_4_2\src\template4.js:27:10), <anonymous>:7:21)
at render (F:\workspace\javascript workspace\plNode\prj8_5_4_2\src\template4.js:34:9)
at Object.<anonymous> (F:\workspace\javascript workspace\plNode\prj8_5_4_2\src\template4.js:49:13)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
at internal/main/run_main_module.js:17:47
分析原因
- escape不是函数,因为 return new Function(‘obj’, ‘escape’, tpl) 语句中 ‘escape’是函数,complie(data, escape) 调用的时候需要传递 escape函数,否则找不到escape函数
解决方法
方法一
- 调用时,传递escape函数
complie(data, escape)
方法二
- 自己调用自己时,传递escape函数
complie.call(complie, data, escape)
# 或者
complie.call(this, data, escape)
完整代码
var escape = function (html) {
return String(html)
.replace(/&(?!\w+;)/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
}
var complie = function (str) {
console.log(str)
var tpl = str.replace(/<%=([\s\S]+?)%>/g, function (match, code) {
// 转义
return "' + escape(" + code + ") + '"
}).replace(/<%-([\s\S]+?)%>/g, function (match, code) {
// 正常输出
return "' + " + code + " + '"
}).replace(/<%([\s\S]+?)%>/g, function (match, code) {
return "';\n" + code + "\n tpl += '"
}).replace(/\'\n/g, '\'')
.replace(/\n\'/gm, '\'')
console.log('----------代码替换模板----------')
console.log(tpl)
tpl = "tpl = '" + tpl + "'"
tpl = tpl.replace(/''/g, '\'\\n\'')
tpl = ' var tpl = ""\n with (obj || {}) {\n ' + tpl + '\n }\n return tpl'
return new Function('obj', 'escape', tpl)
}
var render = function(complie, data) {
console.log('----------构造函数----------')
console.log(complie.toString())
console.log('----------运行函数----------')
return complie(data, escape)
// 等价于
//return complie.call(this, data, escape)
}
var tpl = [
'<% if (obj.user) { %>',
'<h2><%=user.name%></h2>',
'<% } else { %>',
'<h2>匿名用户</h2>',
'<% } %>'].join('\n')
console.log('----------模板----------')
console.log(tpl)
console.log(render(complie(tpl), {user: {name: 'Jackson Tian'}}))
//console.log('\n\n')
//console.log(render(complie(tpl), {}))