函数对象和 ES 模块的范围问题
Scope problem with Function object and ES Modules
几天来我一直遇到这个问题,我正在开发客户端框架,最近我将其切换为使用 ES 模块。问题是我的模板引擎现在遇到范围问题:我无法再在我的视图中调用辅助函数。
代码如下:
class templateEngine {
// Parse template (content) with parameters
static parse(content, params) {
let re = /{#(.+?)#}/g,
reExp = /(^\s*(if|for|else|switch|case|break|{|})).*/g,
code = 'with(obj) { var r=[];\n',
cursor = 0,
result,
match;
let add = function (line, js) {
js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
(code += line != '' ? 'r.push("' + line.replace(/"/g, '\"') + '");\n' : '');
return add;
}
while (match = re.exec(content)) {
add(content.slice(cursor, match.index))(match[1], true);
cursor = match.index + match[0].length;
}
add(content.substr(cursor, content.length - cursor));
code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, ' ');
try {
test("test"); // This console log "test".
result = new Function('obj', code).call(this, params);
}
catch (err) {
console.error(err.message, "falling back to raw content.");
return content;
}
return result;
};
};
function test(s) {
console.log(s);
return s;
}
export default templateEngine;
下面是我如何调用解析函数(这个加载函数是视图的一部分 class):
// Load parsed template view into "viewroot"
load() {
let params = this.params;
let xhr = new XMLHttpRequest();
xhr.overrideMimeType("text/html");
xhr.open('GET', this.path, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == "200") {
// Parse view template
let parsedview = templateEngine.parse(this.responseText, params);
// Load parsed html into viewroot element
document.querySelector("viewroot").innerHTML = parsedview;
// Change page title with view title
let title = document.querySelector("viewhead").querySelector("title");
document.title = title.text;
}
};
xhr.send(null);
}
这里是 html 模板:
<viewhead>
<title>Welcome!</title>
</viewhead>
<viewbody>
<div class="container">
<h1 class="title">Page title</h1>
<p class="description">welcome to this page</p>
<p>{# test("test") #}</p>
</div>
</viewbody>
无法再从 "result" 函数对象访问 "test" 函数。
原版 javascript 和非模块功能可访问且有效,但模块功能则不然。
希望你能帮我解决这个问题。
我通过实验找到了答案,我只是在 scope
对象中添加了我想使用模板访问的函数并使用 apply(scope, [params])
.
代码如下:
let scope = params;
scope.myFunction = myFunction;
result = new Function('obj', code).apply(scope, [params]);
希望它能帮助人们找到这个答案。
几天来我一直遇到这个问题,我正在开发客户端框架,最近我将其切换为使用 ES 模块。问题是我的模板引擎现在遇到范围问题:我无法再在我的视图中调用辅助函数。
代码如下:
class templateEngine {
// Parse template (content) with parameters
static parse(content, params) {
let re = /{#(.+?)#}/g,
reExp = /(^\s*(if|for|else|switch|case|break|{|})).*/g,
code = 'with(obj) { var r=[];\n',
cursor = 0,
result,
match;
let add = function (line, js) {
js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
(code += line != '' ? 'r.push("' + line.replace(/"/g, '\"') + '");\n' : '');
return add;
}
while (match = re.exec(content)) {
add(content.slice(cursor, match.index))(match[1], true);
cursor = match.index + match[0].length;
}
add(content.substr(cursor, content.length - cursor));
code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, ' ');
try {
test("test"); // This console log "test".
result = new Function('obj', code).call(this, params);
}
catch (err) {
console.error(err.message, "falling back to raw content.");
return content;
}
return result;
};
};
function test(s) {
console.log(s);
return s;
}
export default templateEngine;
下面是我如何调用解析函数(这个加载函数是视图的一部分 class):
// Load parsed template view into "viewroot"
load() {
let params = this.params;
let xhr = new XMLHttpRequest();
xhr.overrideMimeType("text/html");
xhr.open('GET', this.path, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == "200") {
// Parse view template
let parsedview = templateEngine.parse(this.responseText, params);
// Load parsed html into viewroot element
document.querySelector("viewroot").innerHTML = parsedview;
// Change page title with view title
let title = document.querySelector("viewhead").querySelector("title");
document.title = title.text;
}
};
xhr.send(null);
}
这里是 html 模板:
<viewhead>
<title>Welcome!</title>
</viewhead>
<viewbody>
<div class="container">
<h1 class="title">Page title</h1>
<p class="description">welcome to this page</p>
<p>{# test("test") #}</p>
</div>
</viewbody>
无法再从 "result" 函数对象访问 "test" 函数。
原版 javascript 和非模块功能可访问且有效,但模块功能则不然。
希望你能帮我解决这个问题。
我通过实验找到了答案,我只是在 scope
对象中添加了我想使用模板访问的函数并使用 apply(scope, [params])
.
代码如下:
let scope = params;
scope.myFunction = myFunction;
result = new Function('obj', code).apply(scope, [params]);
希望它能帮助人们找到这个答案。