为什么我可以在JavaScript中定义之前使用函数?

时间:2008-11-04 11:35:41

标签: javascript function

此代码始终有效,即使在不同的浏览器中也是如此:

function fooCheck() {
  alert(internalFoo()); // We are using internalFoo() here...

  return internalFoo(); // And here, even though it has not been defined...

  function internalFoo() { return true; } //...until here!
}

fooCheck();
但是,我找不到一个单一的参考,为什么它应该工作。 我第一次在John Resig的演示文稿中看到过这个,但它只是提到了。在那里或那里没有任何解释。

有人可以赐教我吗?

7 个答案:

答案 0 :(得分:196)

function声明是魔术并且导致其标识符在其代码块*中的任何内容被执行之前被绑定。

这与具有function表达式的赋值不同,后者以正常的自上而下顺序进行评估。

如果您将示例更改为:

var internalFoo = function() { return true; };

它会停止工作。

函数声明在语法上与函数表达式完全分离,即使它们看起来几乎相同,但在某些情况下可能不明确。

ECMAScript standard部分 10.1.3 中记录了这一点。不幸的是,即使按标准标准,ECMA-262也不是一个非常易读的文件!

*:包含函数,块,模块或脚本。

答案 1 :(得分:16)

它被称为HOISTING - 在定义函数之前调用(调用)函数。

我想写的两种不同类型的函数是:

表达功能&减速功能

  1. 表达式功能:

    函数表达式可以存储在变量中,因此它们不需要函数名称。它们也将被命名为匿名函数(没有名称的函数)。

    要调用(调用),他们总是需要使用 变量名称 。如果在定义之前调用这意味着在此处不发生提升,则这些类型的功能将不起作用。我们必须首先定义表达式函数然后再调用它。

    let lastName = function (family) {
     console.log("My last name is " + family);
    };
    let x = lastName("Lopez");
    

    这是你可以用ECMAScript 6编写的:

    lastName = (family) => console.log("My last name is " + family);
    
    x = lastName("Lopez");
    
  2. 减速功能:

    使用以下语法声明的函数不会立即执行。它们“保存供以后使用”,并且在调用(调用)时将在稍后执行。如果您在定义它们之前或之后调用它们,这些类型的函数都有效。如果在定义之前调用减速功能 - 提升 - 正常工作。

    function Name(name) {
      console.log("My cat's name is " + name);
    }
    Name("Chloe");
    

    吊装示例:

    Name("Chloe");
    function Name(name) {
       console.log("My cat's name is " + name);
    }
    

答案 2 :(得分:13)

浏览器从头到尾读取您的HTML,并且可以在读取并解析为可执行的块(变量声明,函数定义等)时执行它。但是在任何时候都只能使用脚本之前定义的内容。点。

这与处理(编译)所有源代码的其他编程上下文不同,可能将它与您需要解析引用的任何库链接在一起,并构造可执行模块,此时执行开始。

您的代码可以引用进一步定义的命名对象(变量,其他函数等),但在所有部分都可用之前,您无法执行引用代码。

当您熟悉JavaScript时,您会非常清楚自己需要按正确顺序编写内容。

修订:要确认接受的答案(上面),请使用Firebug逐步浏览网页的脚本部分。你会看到它在功能之间跳过,在实际执行任何代码之前只访问第一行。

答案 3 :(得分:3)

某些语言要求在使用前必须定义标识符。原因是编译器在源代码上使用单个传递。

但如果有多次通过(或某些检查被推迟),你可以完全没有这个要求。 在这种情况下,可能首先读取(和解释)代码,然后设置链接。

答案 4 :(得分:2)

我只使用了一点JavaScript。我不确定这是否会有所帮助,但它看起来与您所说的非常相似,可能会给出一些见解:

http://www.dustindiaz.com/javascript-function-declaration-ambiguity/

答案 5 :(得分:0)

函数“internalFoo”的主体需要在解析时去某处,所以当JS解释器读取代码(也就是解析)时,会创建函数的数据结构并分配名称。

只是稍后,然后代码运行,JavaScript实际上试图找出“internalFoo”是否存在以及它是什么以及是否可以调用等等。

答案 6 :(得分:-4)

出于同样的原因,以下内容始终将foo放在全局命名空间中:

if (test condition) {
    var foo;
}