html 中脚本插入的奇怪行为

Weird behavior on script insertion in html

我想在页脚 html 部分插入 2 个脚本,但我有一个奇怪的行为。如果我在 html 本身中使用标签手动插入,它会起作用 (index1.html)。但是,如果我使用 IIFE 创建标签并将它们插入相同的位置和相同的顺序 (index2.html),则控制台中会显示一条错误消息 'dummy variable is not defined'。常识告诉我这个错误很好(因为 dummy 是在使用后定义的),但为什么它适用于 index1.html?

index1.html:

    ...
    <script src="script1.js" async></script>
    <script src="script2.js"></script>
    </body>
</html>

index2.html:

    ...
    <script>
        (function(){
            var loadScript = function(data, callback) {
                var script = document.createElement('script');
                script.src = data.src;
                if (data.opts) {
                    if (data.opts.async) script.async = data.opts.async;
                }
                document.body.appendChild(script);
            }

            var loadScriptRecursive = function(scripts, index) {
                loadScript(scripts[index], function () {
                    if (++index < scripts.length) loadScriptRecursive(scripts, index);
                });
            }

            var scripts = [{src: 'script1.js'}, {src: 'script2.js', opts: {async: false}}];
            loadScriptRecursive(scripts, 0);
        })()
    </script>

    </body>
</html>

script1.js:

$(document).ready(function () {
    if (dummy) ...
    ...
}

script2.js:

var dummy = true

首先,您声明了 callback 但从未使用过。我假设你的意思是这样的 script.onload = callback;.

(function() {
  var loadScript = function(data, callback) {
    var script = document.createElement("script");
    script.src = data.src;
    script.onload = callback; // NEW LINE
    if (data.opts) {
      if (data.opts.async) script.async = data.opts.async;
    }
    document.body.appendChild(script);
  };

  var loadScriptRecursive = function(scripts, index) {
    loadScript(scripts[index], function() {
      if (++index < scripts.length) {
        loadScriptRecursive(scripts, index);
      }
    });
  };

  var scripts = [
    { src: "script1.js" },
    { src: "script2.js", opts: { async: false } }
  ];
  loadScriptRecursive(scripts, 0);
})();

但这还不足以解决这个问题,因为 $(document).ready()

让我们看看文档是怎么说的:

The .ready() method offers a way to run JavaScript code as soon as the page's Document Object Model (DOM) becomes safe to manipulate. [jQuery]

The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. [MDN]

在第一个示例中,DOMContentLoaded 在加载 JS 文件后触发:

在第二个示例中,DOMContentLoaded 立即触发,无需等待 JS 文件:


这就是为什么您需要使用 $(window).on("load", function() {}); 而不是 $(document).ready(function() {});