Для тех, кто все еще пытается это сделать, нет, вы не можете вставлять скрипт с помощью innerHTML
, но можно загрузить строку в тег скрипта с помощью Blob
и URL.createObjectURL
.
Я создал пример, который позволяет запускать строку как скрипт и получать «экспорт» скрипта, возвращенного с помощью обещания:
function loadScript(scriptContent, moduleId) {
// create the script tag
var scriptElement = document.createElement('SCRIPT');
// create a promise which will resolve to the script's 'exports'
// (i.e., the value returned by the script)
var promise = new Promise(function(resolve) {
scriptElement.onload = function() {
var exports = window["__loadScript_exports_" + moduleId];
delete window["__loadScript_exports_" + moduleId];
resolve(exports);
}
});
// wrap the script contents to expose exports through a special property
// the promise will access the exports this way
var wrappedScriptContent =
"(function() { window['__loadScript_exports_" + moduleId + "'] = " +
scriptContent + "})()";
// create a blob from the wrapped script content
var scriptBlob = new Blob([wrappedScriptContent], {type: 'text/javascript'});
// set the id attribute
scriptElement.id = "__loadScript_module_" + moduleId;
// set the src attribute to the blob's object url
// (this is the part that makes it work)
scriptElement.src = URL.createObjectURL(scriptBlob);
// append the script element
document.body.appendChild(scriptElement);
// return the promise, which will resolve to the script's exports
return promise;
}
...
function doTheThing() {
// no evals
loadScript('5 + 5').then(function(exports) {
// should log 10
console.log(exports)
});
}
Я упростил это из своего фактическая реализация, поэтому нет обещаний о том, что в нем нет ошибок. Но принцип работает.
Если вам не нужно возвращать какое-либо значение после запуска скрипта, это еще проще; просто оставьте Promise
и onload
бит. Вам даже не нужно обернуть скрипт или создать глобальное свойство window.__load_script_exports_
.