是什么决定了JavaScript模块在.html中的执行顺序?

是什么决定了JavaScript模块在.html中的执行顺序?,javascript,Javascript,我读过。这不是真的 在我提出这个问题之前,我学到了: 首先执行没有导入的模块(叶模块) 导入的模块在从中导入的模块执行之前不会执行 这使我能够解释一个基本场景,如下所示: 2.js记录2并导出functionTwo(调用时,记录“2-export”)。 1.js记录1并从2.js导入和执行functionTwo 无论这些模块的源代码顺序如何,2.js总是先执行,因为1.js不能在2.js之前执行-它依赖于导出到它的东西2.js。控制台始终显示:“2,1,2-export” 但是,对于这两种情

我读过。这不是真的

在我提出这个问题之前,我学到了:

  • 首先执行没有导入的模块(叶模块)
  • 导入的模块在从中导入的模块执行之前不会执行

  • 这使我能够解释一个基本场景,如下所示:

    2.js
    记录
    2
    并导出
    functionTwo
    (调用时,记录
    “2-export”
    )。
    1.js
    记录
    1
    并从
    2.js
    导入和执行
    functionTwo

    无论这些模块的源代码顺序如何,
    2.js
    总是先执行,因为
    1.js
    不能在
    2.js
    之前执行-它依赖于导出到它的东西
    2.js
    。控制台始终显示:“2,1,2-export”


    但是,对于这两种情况,这是一个不完整的答案:

  • ModuleA从ModuleB导入。ModuleB从ModuleA导入
  • ModuleA从ModuleB导入。ModuleC从ModuleD导入。我一直在试验源代码顺序,但我无法直观地掌握决定模块执行完整顺序的规则。我只知道D或B必须先执行。(有时DB或BD先执行;有时DC或BA先执行)

  • 附言


    我们讨论的规则是否只适用于没有
    async
    属性的模块?具有
    async
    属性的模块是否真的会在加载后立即执行?

    规则非常简单:首先导入依赖树的叶子(它们的代码正在执行),然后是所有中间模块,直到根模块

    这就是你观察到这种行为的原因:

    • 1
      是一个叶模块,它首先执行(
      console.log('1')
      functionExport
      声明)
    • 2
      导入
      1
      ,因此它将在(
      console.log('2')之后立即执行
    • 2
      最终从
      1
      调用函数(
      console.log('1export'
    事实上,没有明确说明导入是否应该按顺序处理。有些浏览器可能有顺序导入,而有些浏览器可能没有

    如果你想保证一定的执行顺序,并在浏览器间保持一致的行为,你必须相应地指定一个导入链。两个导入链不能保证分别执行(这就是为什么有时你会先看到DB,而不是DC)。 两个导入链不能保证按特定顺序执行(这就是为什么有时会看到DB,有时会看到BD)

    唯一可以保证的是,脚本在其导入已经执行之后执行


    关于
    async
    属性的最后一句话,它允许在浏览器继续解析页面时延迟抓取和执行。它适用于
    module
    脚本,就像普通脚本一样,唯一的区别是它们也加载依赖项,以符合上述规则。

    你是说
    2.js
    1.js
    导入
    functionExport
    ?如果是这样的话,那么
    1.js
    最终会首先被加载,因为
    2.js
    需要它的一些东西。@GhassenLouhaichi 1.Yes.2.如果
    1.js
    需要从
    2.js
    中加载一些东西会发生什么?我只是从我的qu中链接的页面学习估计。我在哪里可以看到一组完整的规则?然后您将创建一个循环依赖项,它将导致一个错误,因为其中一个必须在另一个之前加载,所以它无法从第二个中找到它需要的任何内容(因为它尚未加载).2.js仍然是先加载的,但由于它依赖于1.js,因此在加载并执行1.js之前将不会执行。感谢您的回复@GuerricP。依赖树是什么?什么是叶模块?是什么使模块成为叶模块?这不是事实它导出了一些东西,是吗?如果你不介意的话,可能需要避免(或至少解释)术语,首先用简单的词来表达它!我们通常将从导入链生成的结构称为“依赖树”。“叶模块”是一个不导入任何东西的模块,然后是“分支”是一个导入链,一直到根模块(在任何地方都没有导入):树的主干。这只是一个简单的隐喻,实际上是定义由链接在一起的节点组成的结构的常用技术词汇。@Guerric因此,如果没有任何模块导入任何内容,则加载顺序完全由源顺序决定(脚本在页面上显示的顺序).一旦模块导入了某些内容,它就会进入que的后面-或者至少不再是源订单裁定的一部分。恐怕我不太理解树的类比。这些信息是否正式化并记录在某个地方了?@Guerric P.s.我应该提到-我们所说的裁定是否适用于modu具有
    defer
    属性而不具有
    async
    属性的LE。是否存在这样的情况:具有
    async
    属性的模块会尽快加载,并且我们所讨论的规则都不适用于它们?解析和加载是否意味着相同的事情?