jquery引用错误和执行顺序?

Posted

技术标签:

【中文标题】jquery引用错误和执行顺序?【英文标题】:jquery reference error and execution order? 【发布时间】:2015-09-17 17:51:05 【问题描述】:

我在理解一般的 javascript/jquery 执行顺序以及存储 js 的正确位置时遇到了问题。我现在正在尝试重新组织我的代码,并不断遇到同样的问题,这让我对所有的 javascript 越来越感到沮丧。

我正在构建一个带有 Jinja2 模板的 Python+Flask webapp,其中包含各种 jquery 内容。最初我有一些看起来有点像这样的标准 html 代码......

<html>
 <head>
    <script type="text/javascript" src="url_for('static',filename='js/jquery/jquery-1.11.2.min.js')"></script>
    <script type="text/javascript" src="url_for('static',filename='js/bootstrap/bootstrap.min.js')"></script>
    <script type="text/javascript" src="url_for('static',filename='js/utils.js')"></script>

    <script type='text/javascript'>
       # get hash from page
       function getHash() 
          var hash = window.location.hash;
          var newhash = hash.slice(hash.search('_')).replace('_','#');
          return newhash;
       

      // Load ifu div element if hash present when page loads
      $(function()
        var ifuhash = getHash();
        var ifu = ifuhash.slice(ifuhash.search('#')+1);
        $(String(ifuhash)).fadeIn();    
        if (hash.search('comment') >= 0) $(String(hash)).fadeIn();
      );           

      ... other js ....

    </script>
 </head>

 <body>
    % include 'header.html' %
 </body>
</html>

这运行得很好。但是由于一个好的做法似乎是将所有 JS 放在他们自己的文件中,以免弄乱 html,我正在尝试将我当前的 javascript 代码重新组织为我认为应该工作的内容,但我遇到了问题.

getHash 函数在多个页面中是通用的,所以我把它拉出来并粘贴在一个单独的 js 中,称为 plateinfo.js,这样我的代码就是现在

<html>
 <head>
    <script type="text/javascript" src="url_for('static',filename='js/jquery/jquery-1.11.2.min.js')"></script>
    <script type="text/javascript" src="url_for('static',filename='js/bootstrap/bootstrap.min.js')"></script>
    <script type="text/javascript" src="url_for('static',filename='js/utils.js')"></script>
    <script type="text/javascript" src="url_for('static',filename='js/plateinfo.js')"></script>

    <script type='text/javascript'>
      // Load ifu div element if hash present when page loads
      $(function()
        var ifuhash = getHash();
        var ifu = ifuhash.slice(ifuhash.search('#')+1);
        $(String(ifuhash)).fadeIn();    
        if (hash.search('comment') >= 0) $(String(hash)).fadeIn();
      );           

      ... other js ....

    </script>
 </head>

 <body>
   % include 'header.html' %
 </body>
</html>

plateinfo.js 看起来像

// Toggle add comment login function
$(function() 
    $('#addcommentbut').click(function() 
        var fxn = 'grabComments';
        $('#fxn').val(fxn);
    );
);

// Get IFU hash from page
function getHash() 
    var hash = window.location.hash;
    var newhash = hash.slice(hash.search('_')).replace('_','#');
    return newhash;


// Render Tags in div
function renderTags(hash) 
  ..does stuff

但是,当我这样做时,我现在得到了错误

ReferenceError: getHash 未定义

该函数在 DOM 范围之外,应该是可导入的。而我之前已经成功地做到了这一点。 utils.js 文件包含完美运行的独立函数。我已清除缓存,重新启动浏览器以刷新会话,重新启动计算机,但似乎没有任何效果。那么有什么关系呢?我认为 html/js 代码的执行顺序是从上到下的。那么这里的最佳做法是什么?正确的导入/执行顺序是什么?

更新以显示执行顺序: 所以我像这样放了一堆console.logs

<html>
 <head>
    <script type="text/javascript" src="url_for('static',filename='js/jquery/jquery-1.11.2.min.js')"></script>
    <script type="text/javascript" src="url_for('static',filename='js/bootstrap/bootstrap.min.js')"></script>

 <script type='text/javascript'>$(function() console.log('before utils.js'););</script>
    <script type="text/javascript" src="url_for('static',filename='js/utils.js')"></script>
<script type='text/javascript'>$(function() console.log('after utils.js'););</script>

<script type='text/javascript'>$(function() console.log('before plateinfo.js'););</script>
    <script type="text/javascript" src="url_for('static',filename='js/plateinfo.js')"></script>
<script type='text/javascript'>$(function() console.log('after plateinfo.js, before last script'););</script>

    <script type='text/javascript'>
      console.log('start of last script');

      // Load ifu div element if hash present when page loads
      $(function()
        console.log('calling gethash');
        var ifuhash = getHash();
        var ifu = ifuhash.slice(ifuhash.search('#')+1);
        $(String(ifuhash)).fadeIn();    
        if (hash.search('comment') >= 0) $(String(hash)).fadeIn();
      );           

      ... other js ....

    </script>
 </head>

 <body>
   % include 'header.html' %
 </body>
</html>

这是日志输出

before utils.js plateInfo.html:40:1
after utils.js plateInfo.html:44:1
start of last script plateInfo.html:204:5
before plateinfo.js plateInfo.html:185:3
after plateinfo.js, before last script plateInfo.html:189:15
calling gethash plateInfo.html:221:3
ReferenceError: getHash is not defined plateInfo.html:222:6

这是为什么?

另外: 在 javascript 中引用我的 Jinja2 模板变量时,我也遇到了单独但相关的问题。我包含的这个 header.html 文件正在发生这种情况。如果我将所有 js 代码包含在同一个 html 文件中,它就可以正常工作。但是当我将 js 移动到单独的 header.js 时,模板变量不再被正确引用。也许这值得单独发布。

【问题讨论】:

我认为 url_for('static',filename='js/plateinfo.js') 是在 DOM 准备好之后被评估的,所以你的内联脚本在你之前触发脚本全部加载。我可能会尝试在代码中的不同位置插入 console.logs,以便您可以跟踪组件的加载时间。 所以,是的,我试过了,但它似乎把所有事情都搞砸了。它跳过了console.logs,然后再回到它们。我不知道是怎么回事。如果它以正确的顺序发生,那么为什么没有定义该方法。我已经编辑了文本以更新日志顺序。 @Neil Jinja 是一种 Python 模板语言;我几乎可以肯定它将在服务器上而不是在浏览器中进行评估。 不要将你的 console.logs 放在 jQuery onload 方法中。它们都被同时执行,一个接一个。更好的方法是将 console.log 调用直接放在文件本身(utils.js、plateinfo.js)中 【参考方案1】:

getHash() 未定义为全局函数。它是私有的,仅属于您告诉 jQuery 在页面加载时运行的 plateinfo.js 中的函数。您的代码当前设置的方式,您无法在其他任何地方使用它。但是在你的内联 JS 中,这就是你想要做的:

var ifuhash = getHash();

您可以让getHash() 全球可用:

function getHash() 
  // ...


window.getHash = getHash;

但这通常被认为是糟糕的编码习惯。构建代码的更好方法是使用 namespaces 将所有自定义函数和对象保存在一个位置并将其附加到 window

<script type="text/javascript">
  window.myNamespace = window.myNamespace || ;
  window.myNamespace.getHash = function() 
    return 123;
  ;
</script>
<script type="text/javascript">
  $(function() 
    var foo = window.myNamespace.getHash(); // foo now equals 123
  );
<script>

【讨论】:

啊,我错误地解析了您的plateinfo.js 文件。但我仍然敢打赌,您的问题与您声明函数的范围以及您尝试运行它的范围有关。 他已经在全局命名空间中声明了 getHash,这不是闭包。仅仅因为函数声明在一个单独的文件中,并不意味着它没有在全局范围内声明。 我认为这就是答案。我最终重写了整个 plateinfo.js,所以它是一个对象,我在我的主代码块中对其进行了实例化。我将 getHash 转换为在初始化时运行的函数,并将结果存储在对象的变量中。这似乎简化并解决了我的问题。

以上是关于jquery引用错误和执行顺序?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery:强制执行 document.ready() 调用的顺序

Unity3D中脚本的执行顺序和编译顺序(vs工程引用关系)

jquery中各个事件执行顺序如下:

jquery绑定函数在Firefox和Chrome之间有不同的执行顺序

jquery中各个事件执行顺序如下:

jquery ajax中success与complete的执行顺序