【问题标题】:JavaScript: When does JavaScript evaluate a function, onload or when the function is called?JavaScript:JavaScript 何时评估函数、onload 或函数何时被调用?
【发布时间】:2010-05-11 16:22:13
【问题描述】:

JavaScript 何时评估函数?是在页面加载时还是在调用函数时?

之所以这么问是因为我有如下代码:

function scriptLoaded() {
   // one of our scripts finished loading, detect which scripts are available:
   var jQuery = window.jQuery;
   var maps = window.google && google.maps;

   if (maps && !requiresGmaps.called) {
     requiresGmaps.called = true;
     requiresGmaps();
   }
   if (jQuery && !requiresJQuery.called) {
     requiresJQuery.called = true;
     requiresJQuery();
   }
   if (maps && jQuery && !requiresBothJQueryGmaps.called) {
     requiresBothJQueryGmaps.called = true;
     requiresBothJQueryGmaps();
   }
}
// asynch download of script
function addScript(url) {
    var script = document.createElement('script');
    script.src = url;
    // older IE...
    script.onreadystatechange=function () {
      if (this.readyState == 'complete') scriptLoaded.call(this);
    }
    script.onload=scriptLoaded;

    document.getElementsByTagName('head')[0].appendChild(script);
}

addScript('http://google.com/gmaps.js');
addScript('http://jquery.com/jquery.js');

// define some function dependecies
function requiresJQuery() { // create JQuery objects }
function requiresGmaps() { // create Google Maps object, etc }
function requiresBothJQueryGmaps() { ... }

我想要做的是异步下载我的 JavaScript 并尽早开始执行这些脚本,但我的代码依赖于脚本何时被明显下载和加载。

当我尝试上面的代码时,我的浏览器似乎仍在尝试评估我的 require* 函数中的代码,甚至在这些函数被调用之前。它是否正确?还是我误解了我的代码有什么问题?

【问题讨论】:

  • 这个问题只有在你足够聪明地将你的 JavaScript 从你的标记中放入一个外部文件时才有意义。如果你缺乏这样的智慧,那么你应该期待不确定性和混乱。

标签: javascript jquery google-maps asynchronous


【解决方案1】:

函数在调用时进行评估。

例如

function test() {
    window.foo = 'bar';
}

console.log(window.foo); // => undefined
test();
console.log(window.foo); // => bar

即使 test 是在第一个 console.log 之前创建的,window.foo 也不会在实际调用 test 之前填充。

如果您的requires* 函数处于挂起/阻塞状态,那么您需要显示这些函数的代码(为什么不提供有问题的函数的源代码?)

编辑

目前,当您将已加载的 <script> 附加到 <head> 时,您的网站正在空白处。

无论如何,一个快速的解决方法是将您想要的脚本放在页面底部附近,在</body> 之前,因为只有<head> 中的脚本会在加载时完全阻止页面。

有一些优雅的方法可以延迟加载资源,但是,为了简单起见..

<script type="text/javascript" src="http://path/to/jquery.js"></script>
<script type="text/javascript">
requiresJQuery(); // jQuery is available at this point
</script>
</body>

关键是,由于&lt;script&gt; 放置在您的主要元素之后,因此 DOM 元素将在浏览器开始下载您的其他库之前可用(并且可能已加载)。

【讨论】:

  • @Matt,我现在链接到原始帖子中的实时站点。查看更新。
  • @Matt,也 - 我基本上是在寻找使我的网站加载速度更快的方法,而我注意到的一个重要问题是 JS 阻塞。您可以在 / 看到我的实时网站。我试图对链接的 html 页面做的是修改我的首页以删除继承 JS 阻塞,以便在可能的情况下执行早期的 JS 处理(如果有意义的话)
  • @Matt,请参阅我之前的评论。我不想阻塞,我想异步下载我的 JS。您刚刚在 EDIT 中描述的不是让 JS 块而不是异步下载吗?
  • @Benj - 我的回答中的策略只是“感知”异步。它实际上会阻塞,但只有在 DOM 加载之后(因为 &lt;script&gt; 就在 &lt;/body&gt; 之前)。对于“真正的”异步,您需要查看类似 LazyLoad 的内容
  • @Matt,我认为我没有很好地解释我的问题。我不能延迟加载,因为我绝对 需要 那些 JQuery 来显示我的网站。网站正在动态呈现。 1)网页的主要部分是谷歌地图,所以我不想延迟加载,因为它是网站的一个巨大的视觉组件。然后,我使用 JQuery 来呈现我的页面的另外 1/3,这是要在 Google 地图上显示的房屋。因此,我不想延迟加载——我只想执行真正的异步下载以尽可能快地加载 Google Maps 和 JQuery 库。有意义吗?
【解决方案2】:

是的,你可能误会了。即使您的函数包含语法错误,在您实际调用该函数之前也没有关系。

可能是您从其他地方调用这些函数吗?也许您没有提供准确的代码示例?

【讨论】:

  • 我现在链接到原始帖子中的实时站点。查看更新。
  • 我没有看到指向原始网站的链接。你已经删除了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 2013-02-21
相关资源
最近更新 更多