我想在网页中动态地包括一个脚本标签,但我无法控制它的src,所以src="source.js"可能看起来像这样。

document.write('<script type="text/javascript">')
document.write('alert("hello world")')
document.write('</script>')
document.write('<p>goodbye world</p>')

一般来说

<script type="text/javascript" src="source.js"></script>

在头部工作很好,但有没有其他方法,我可以动态添加source.js使用innerHTML之类的东西?

我已经试过了


当前回答

要做到这一点,唯一的方法是替换文档。使用您自己的函数编写,该函数将在页面底部附加元素。jQuery非常简单:

document.write = function(htmlToWrite) {
  $(htmlToWrite).appendTo('body');
}

如果你有html来文档。像问题样例那样写入块,你需要缓冲htmlToWrite段。也许是这样的:

document.write = (function() {
  var buffer = "";
  var timer;
  return function(htmlPieceToWrite) {
    buffer += htmlPieceToWrite;
    clearTimeout(timer);
    timer = setTimeout(function() {
      $(buffer).appendTo('body');
      buffer = "";
    }, 0)
  }
})()

其他回答

你可以像这样使用document.createElement()函数:

function addScript( src ) {
  var s = document.createElement( 'script' );
  s.setAttribute( 'src', src );
  document.body.appendChild( s );
}

差不多十年过去了,没有人愿意写Promise的版本,所以这里是我的版本(基于这个awnser):

function addScript(src) {
  return new Promise((resolve, reject) => {
    const s = document.createElement('script');

    s.setAttribute('src', src);
    s.addEventListener('load', resolve);
    s.addEventListener('error', reject);

    document.body.appendChild(s);
  });
}

使用

try {
  await addScript('https://api.stackexchange.com/js/2.0/all.js');
  // do something after it was loaded
} catch (e) {
  console.log(e);
}

当脚本异步加载时,它们不能调用document.write。调用将被忽略,并将警告写入控制台。

你可以使用下面的代码来动态加载脚本:

var scriptElm = document.createElement('script');
scriptElm.src = 'source.js';
document.body.appendChild(scriptElm);

只有当您的源文件属于一个单独的文件时,这种方法才有效。

但如果你有源代码作为内联函数,你想要动态加载,并想要添加其他属性到脚本标签,例如类,类型等,那么下面的代码片段将帮助你:

var scriptElm = document.createElement('script');
scriptElm.setAttribute('class', 'class-name');
var inlineCode = document.createTextNode('alert("hello world")');
scriptElm.appendChild(inlineCode); 
document.body.appendChild(scriptElm);

有onload函数,可以在脚本成功加载时调用:

function addScript( src, callback ) {
  var s = document.createElement( 'script' );
  s.setAttribute( 'src', src );
  s.onload=callback;
  document.body.appendChild( s );
}

我写了一个漂亮的小脚本来加载多个脚本:

function scriptLoader(scripts, callback) {

    var count = scripts.length;

    function urlCallback(url) {
        return function () {
            console.log(url + ' was loaded (' + --count + ' more scripts remaining).');
            if (count < 1) {
                callback();
            }
        };
    }

    function loadScript(url) {
        var s = document.createElement('script');
        s.setAttribute('src', url);
        s.onload = urlCallback(url);
        document.head.appendChild(s);
    }

    for (var script of scripts) {
        loadScript(script);
    }
};

用法:

scriptLoader(['a.js','b.js'], function() {
    // use code from a.js or b.js
});