如何动态执行/评估包含ES6模块的JavaScript代码/需要一些依赖项?

How to dynamically execute/eval JavaScript code that contains an ES6 module / requires some dependencies?

我希望我的用户能够在我的javascript应用程序中使用javascript作为脚本语言。为此,我需要动态地执行源代码。

动态执行javascript有两个主要选项:

a)采用eval(...)法(或var func = new Function(...);法)。

b)将一个节点添加到dom中(例如使用$('body').append(...))。

只要在动态执行的源代码中不使用任何import语句,这两种方法都可以很好地工作。如果我包括import语句,我会得到错误消息Unexpected identifier

要执行的用户源代码示例:

1
2
3
4
5
6
7
import Atom from './src/core.atom.js':

window.createTreeModel = function(){
   var root = new Atom('root');
   root.createChildAtom('child');
   return root;
}

示例应用程序代码以说明该动态代码的可能用法:

a)使用EVE

1
2
3
4
5
var sourceCode =  editor.getText();
window.createTreeModel = undefined;
eval(sourceCode);
var model = window.createTreeModel();
treeView.setModel(model);

b)使用DOM修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
var sourceCode =  editor.getText();
window.createTreeModel = undefined;

var script ="<script >
"
+
            sourceCode +"
"
+            
           "";

$('body').append(script);

var model = window.createTreeModel();
treeView.setModel(model);

如果我没有指定脚本类型或对选项B使用type="application/javascript",我会得到Unexpected identifier错误。如果我使用type="module",我不会出错。脚本标记已成功添加到DOM,但未执行模块代码。

我首先想到这可能是由于异步加载。但是,等待脚本标记加载完成之前,type='module'不起作用。加载机构与type="application/javascript"一起工作,但是…再一次。。。import不起作用。

脚本标记加载后异步执行的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function loadScript(sourceCode, callback){
        // Adding the script tag to the head as suggested before
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.type = 'application/javascript';
        script.innerHTML = sourceCode;
        //script.async=false;

        // Then bind the event to the callback function.
        // There are several events for cross browser compatibility.
        script.onreadystatechange = callback;
        script.onload = callback;

        // Fire the loading
        head.appendChild(script);
    }

——

1
2
3
4
loadScript(sourceCode, function(){
        var model = window.createModel();
        console.log('model:' + model);
     });

如果我使用在index.html中硬编码用户源代码,则执行模块代码。动态加载模块代码似乎不起作用。我使用的是Chrome版本63.0.3239.108。

=>i.动态添加到dom后,如何强制执行