函数对象和 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]);

希望它能帮助人们找到这个答案。