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

2022-08-30 01:30:01

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

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的演讲笔记中,但只被提及。关于这个问题,那里或任何地方都没有解释。

有人可以启发我吗?


答案 1

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

这与具有表达式的赋值不同,表达式按正常的自上而下顺序计算。function

如果您将示例更改为:

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

它将停止工作。

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

这在 ECMAScript 标准的第 10.1.3 节中有所记录。不幸的是,ECMA-262即使按照标准标准也不是一个非常可读的文档!

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


答案 2

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

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

表达式函数和声明函数

  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. 声明函数:

    使用以下语法声明的函数不会立即执行。它们被“保存以供以后使用”,并将在以后调用(调用)时执行。如果将这种类型的函数称为 BEFORE 或 AFTER,则此方法的工作原理是已定义 is。如果在定义声明函数之前调用该函数,则提升工作正常。

    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);
    }