document.write、onload 和变量范围问题

发布于 2024-12-27 01:56:33 字数 883 浏览 0 评论 0原文

我一整天都在努力处理 document.write 和 onLoad 函数。

如果你考虑这样的 JS 代码 =>

window.i = 0;
console.log(i + " //should be 0");

document.write("<scr"+"ipt onLoad='onA1Ready()' src='a1.js'><\/sc"+"ript>");

function onA1Ready(){
    document.write("<scr"+"ipt onLoad='onA2Ready()' src='a2.js'><\/sc"+"ript>");
}

function onA2Ready(){
    console.log(i + " //should be 2");
} 

和 a1.js 像这样=>;

i++;
console.log(i + " //should be 1");

和 a2.js 非常相似=>

i++;
console.log(i + " //should be 2");   

我希望最后一个控制台输出等于 2,但这是我从控制台中得到的 =>

0 //should be 0     test.js (line 2)
1 //should be 1     a1.js (line 2)
i is not defined    ERROR i++; a2.js (line 1)
onA2Ready is not defined

我想这个问题与范围有关,但我不知道如何。

如果你们中有人知道这里发生了什么,那就太好了。

I've been struggling all day with the document.write and the onLoad function.

If you consider a JS code like this one =>

window.i = 0;
console.log(i + " //should be 0");

document.write("<scr"+"ipt onLoad='onA1Ready()' src='a1.js'><\/sc"+"ript>");

function onA1Ready(){
    document.write("<scr"+"ipt onLoad='onA2Ready()' src='a2.js'><\/sc"+"ript>");
}

function onA2Ready(){
    console.log(i + " //should be 2");
} 

and a1.js beeing like this =>

i++;
console.log(i + " //should be 1");

and a2.js beeing quite similar =>

i++;
console.log(i + " //should be 2");   

I'd expect the last console output to be equal to 2, but instead here is what I get out of the console =>

0 //should be 0     test.js (line 2)
1 //should be 1     a1.js (line 2)
i is not defined    ERROR i++; a2.js (line 1)
onA2Ready is not defined

I guess this issue is scope related, but I can't figure how.

It would be great if any of you had an idea of what's going on here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

掀纱窥君容 2025-01-03 01:56:33

首先我强烈建议不要使用document.write。这很混乱而且没有必要。

添加脚本标签的处理方式要好得多:

var addScriptWithOnLoad = function(src, fn) {
    var s = document.createElement('script');
    s.setAttribute('type', 'text/javascript');
    s.setAttribute('src', src);
    s.onload = fn;
    document.head.appendChild(s);
};

接下来,您真的不应该像这样使用全局范围,您依赖于浏览器的正常运行,这从来都不是一个安全的选择。您应该在函数之间传递数据。然而,这有点超出了这个答案的范围。

将以下脚本标记放置在 网页 的头部,产生您想要的结果

<script type="text/javascript">
    window.i = 0;
    var addJS = function(src, fn) {
        var s = document.createElement('script');
        s.setAttribute('src', src);
        s.setAttribute('type', 'text/javascript');
        s.onload = fn;
        document.head.appendChild(s);
    };

    console.log(i + " //should be 0");

    var fn1 = function() {
        console.log();
        addJS('a2.js', fn2);
    };

    var fn2 = function() {
        console.log(i + " //should be 2");
    };

    addJS('a1.js', fn1);
</script>

Firstly I would Strongly suggest not using document.write. It's messy and unnecessary.

Adding a script tag is much better handled as such:

var addScriptWithOnLoad = function(src, fn) {
    var s = document.createElement('script');
    s.setAttribute('type', 'text/javascript');
    s.setAttribute('src', src);
    s.onload = fn;
    document.head.appendChild(s);
};

Next you really shouldn't be using the global scope like that, you are relying on the browser playing nice, which is never a safe bet. You should rather be passing data between functions. That is however a bit outside the scope of this answer.

the following script tag, placed in the head of a web page, produces your intended result

<script type="text/javascript">
    window.i = 0;
    var addJS = function(src, fn) {
        var s = document.createElement('script');
        s.setAttribute('src', src);
        s.setAttribute('type', 'text/javascript');
        s.onload = fn;
        document.head.appendChild(s);
    };

    console.log(i + " //should be 0");

    var fn1 = function() {
        console.log();
        addJS('a2.js', fn2);
    };

    var fn2 = function() {
        console.log(i + " //should be 2");
    };

    addJS('a1.js', fn1);
</script>
半衬遮猫 2025-01-03 01:56:33

我在 Chrome 16 上进行了测试,一切都按预期运行。但是,在最新的 FF 中,我收到了您所描述的错误。

我的建议是停止使用邪恶 document.write() 来动态加载脚本。而是使用 DOM 方法。我编写了一个小函数 myLoader() 可以帮助您

window.i = 0;
console.log(i + " //should be 0");

var myLoader = function(filename, fun) {
  var head   = document.getElementsByTagName('head')[0],
      script = document.createElement('script');
  script.type= 'text/javascript';
  script.src = filename;
  if(typeof fun === 'function'){ script.onload = fun; }
  head.appendChild(script);
};


myLoader('a1.js', function(){
  myLoader('a2.js', function() {
    console.log(i + " //should be 2");
  });
});

尝试一下。

我得到的输出

0 //should be 0         a0.js (line 2)
1 //should be 1         a1.js (line 2)
2 //should be 2         a2.js (line 2)
2 //should be 2         a0.js (line 17)

I tested on Chrome 16 and everything ran as expected. However, in the latest FF I got the error you described.

My advice is to stop using the evil document.write() to dynamically load scripts. Instead use DOM methods. I have written a little function myLoader() that can help you

window.i = 0;
console.log(i + " //should be 0");

var myLoader = function(filename, fun) {
  var head   = document.getElementsByTagName('head')[0],
      script = document.createElement('script');
  script.type= 'text/javascript';
  script.src = filename;
  if(typeof fun === 'function'){ script.onload = fun; }
  head.appendChild(script);
};


myLoader('a1.js', function(){
  myLoader('a2.js', function() {
    console.log(i + " //should be 2");
  });
});

Try it out.

The output I get

0 //should be 0         a0.js (line 2)
1 //should be 1         a1.js (line 2)
2 //should be 2         a2.js (line 2)
2 //should be 2         a0.js (line 17)
灯角 2025-01-03 01:56:33

我怀疑 onA1Ready() 被称为 onLoad,它编写了另一个被称为 onLoad 的函数,该函数永远不会被调用,因为文档已经加载。

I suspect that onA1Ready() is called onLoad which writes another function to be called onLoad which never is called as the document is already loaded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文