【问题标题】:Hoisting between different files不同文件之间的吊装
【发布时间】:2010-11-10 13:22:23
【问题描述】:

有没有办法在不同文件中的源代码之间进行函数和变量提升?也就是说,像

//Inside firstfile.js
foo === "bar" //should return true

//Inside secondfile.js
function bar() {
    this.foo = "bar";
}

我想这是不可能的,因为大多数 javascript 引擎会按顺序分别解析和执行不同的文件,但我不确定。

我不知道这是否在 ECMA 的规范中,因为不同文件的解析并不是语言的一部分。

【问题讨论】:

  • 这个好像和吊装没什么关系。
  • @Tim Down 我认为术语“hoist”指的是 Javascript 在其他代码之前解释函数声明。
  • 提升是函数声明和var 语句在代码执行之前解析的结果(在变量实例化阶段),这意味着您可以执行foo(); function foo() { alert("foo"); } 之类的操作。这个问题没有做那样的事情。
  • @Pointy:是的,我知道,但这无关紧要。没有引用第二个文件中定义的函数。事实上,给定的第二个文件的代码本身就是一个函数表达式,这是一个语法错误。
  • 对不起,我有点鲁莽,写了一个函数表达式而不是声明。现在我明白了误解;我已经更正了。

标签: javascript hoisting


【解决方案1】:

我最初认为这是一个比实际看起来更有趣的问题。我认为这个问题的答案是每个<script>元素代表一个单独的Program,每个单独的程序在下一个程序发生任何事情之前都被解析并(至关重要)执行,因此只能看到提升的效果在单个程序中。

例如,在单个脚本中:

<script type="text/javasscript">
    alert(typeof foo);
    function foo() {}
</script>

... 提醒“函数”,因为函数声明已被提升,但将两行拆分为单独的 &lt;script&gt; 元素会改变这一点:

<script type="text/javasscript">
    alert(typeof foo);
</script>
<script type="text/javasscript">
    function foo() {}
</script>

... 警告“未定义”,因为第一个脚本在第二个脚本被解析之前执行。

【讨论】:

  • 是的,这就是我要求的;基本上我只是想要一个确认。只是因为我很好奇:这是浏览器的特殊行为,还是在 ECMA 规范中?
  • 程序的行为在 ECMAScript 规范中得到了很好的定义。我从来没有找到的是指定浏览器中的每个&lt;script&gt; 元素必须创建一个程序。这个问题密切相关:stackoverflow.com/questions/3735406
  • 感谢您对该问题的参考。本质上这是我要问的,但当然,这个问题的发帖人在这方面做得更好!
【解决方案2】:

单独加载的 Javascript 源代码都会影响全局上下文。因此

window.foo = "bar";

在一个源文件中将允许另一个源(随后加载)检查:

if (window.foo === "bar") {
  // do something
}

这必须有效,否则不可能创建像所有流行的 Javascript 框架一样的东西。

“this”关键字只在函数内部有意义,它的值与函数来自的源文件无关(至少,没有任何直接意义)。

edit — 我想这里有趣的是 Javascript 解释器的行为(使用问题中的术语)在评估块中的其他代码之前“提升”函数声明。当浏览器加载它们时,这也是逐个脚本完成的。因此,脚本块中的函数声明在每个块中的其他代码之前被解释,但在加载和评估下一个&lt;script&gt; 标签之前,将完全评估单个&lt;script&gt; 标签。

如果您使用 LabJS 或 enhance.js 之类的东西来加载脚本,事情会变得更加复杂,但我不知道您可以依赖脚本以某种方式“混合在一起”的任何上下文除非 你在服务器上明确地组合它们。

【讨论】:

  • 当然,单独加载的 Javascript 源代码都会影响全局上下文。我的问题是文件是否可以更改以前加载的文件的全局空间。
  • 至于this的使用,在那个上下文中是指全局对象,所以this.foo就是foo。如果两个 sn-ps 在同一个文件中,按照我帖子中显示的顺序,比较将返回 true,即使在比较之后分配了值“bar”。我的问题是这种机制是否可以在不同的文件中工作。
  • 还有@Andrea 该函数中的“this”关键字(没有名称,它并不是很有用)可能是全局上下文引用,或者它可能是别的东西。
  • 谢谢,这正是我所期望的。我只是想确定一下:在编写库时能够做这样的事情真的很有用。
  • @Andrea:是的,恐怕你错了。从这个意义上说,函数声明与函数表达式没有什么不同:它们都创建 Function 对象,并且 this 始终由函数的调用方式指定(例如,作为简单调用、作为方法或使用 call()apply())。您可以将由函数声明创建的函数分配为对象方法,就像任何其他函数一样。
【解决方案3】:

浏览器遇到的所有脚本标签都会立即解析并执行。这是因为 document.write API 可能需要浏览器向 DOM 输出一些内容。这意味着在这种情况下,#script1 必须在 #script2 之前完成。

<script id="script1"></script>
<script id="script2"></script>

您可能想检查使用 ASYNC 和 DEFER 属性时的行为。 Webkit 支持它们。

【讨论】:

    猜你喜欢
    • 2019-11-02
    • 1970-01-01
    • 2016-07-12
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-11
    相关资源
    最近更新 更多