为什么要在脚本中声明和定义函数之前先调用它?

时间:2019-11-21 04:34:38

标签: javascript function

以下是我的意思的示例代码,摘自How to JS Animate (W3 Schools via W3schools.com)

示例代码:

function myMove() 
    {
          var elem = document.getElementById("myAnimation");
          var pos = 0;
          var id = setInterval(frame, 10);
          function frame()
          {
            if (pos == 350) {
              clearInterval(id);
            } else {
              pos++;
              elem.style.top = pos + 'px';
              elem.style.left = pos + 'px';
            }
          }
    } 

在上面的特定示例代码中,出于具体考虑,我将提出相同的问题。

问题:

  

为什么setInterval(frame,x)可以调用frame(),即使在将setInterval()分配给   “ id”变量减速度?

背景
我是一位自学成才的C / C ++编码器,涉足Web开发领域。我已经读过ES6变量的“提升”,但是我不确定是不是同样发生在函数上。在C ++和C中,您无法做到这一点(据我了解)!所以,请有人帮帮我!

谢谢!

4 个答案:

答案 0 :(得分:1)

感谢Hoisting。假设您的函数定义将移至脚本顶部。就这样,尽管其定义在下面,您仍可以调用frame()

答案 1 :(得分:0)

到目前为止,主持人[edit:not a mod!]给出了答案,指出...

它正在吊起(一种编程概念)。

在JavaScript中:

  • 起吊适用于功能
  • 吊装适用于“ var”类型的变量
  • 起吊不适用于:
    • “让”类型变量
    • “ const”类型的对象/常量
    • “表情”(不确定含义)

他提供的链接在这里,它解释了许多细微差别: Hoisting on MDN

答案 2 :(得分:0)

当您的代码经过阶段时,

  1. 编译
  2. 执行

在编译阶段Hoisting将发生,在该阶段所有函数声明都将置于其作用域的顶部。

当您的代码由JS引擎编译时,将被视为:

function myMove() 
{   

    function frame()
    {
        if (pos == 350) {
            clearInterval(id);
        } else {
            pos++;
            elem.style.top = pos + 'px';
            elem.style.left = pos + 'px';
        }
    }
    var elem;
    var pos;
    var id;

    elem = document.getElementById("myAnimation");
    pos = 0;
    id = setInterval(frame, 10);

} 

注意:

  1. 所有函数都在变量之前悬挂。
  2. letconst声明的变量不符合吊装条件。
  3. Function expressions不符合吊装条件。

编辑:函数表达式:

还可以使用表达式定义JavaScript函数。

函数表达式可以存储在变量中:

var x = function (a, b) {return a * b};

将函数表达式存储在变量中之后,该变量可以用作函数。存储在变量中的函数不需要函数名。总是使用变量名来调用(调用)它们。

答案 3 :(得分:0)

我相信带有函数声明:

growl();

function growl() {
    return "Grr!";
}

JavaScript将首先运行函数声明代码。

但是,如果我创建这种类型的功能:

hoot();

var hoot = function() {
    return "hoo! hoo!";
}

我会得到:

TypeError: hoot is not a function

为什么?因为我们使用的是函数表达式,所以它们并不完全悬挂。我说的不完全是因为JavaScript读取了var hoot,但它不知道它的值,因此它将其设置为undefined,并尝试调用undefined

因此,该变量已被吊起,但该值未被吊起。

如果我这样尝试会怎样?

hoot();

let hoot = function() {
    return "hoo! hoo!";
}

我会收到以下错误:

ReferenceError: Cannot access 'hoot' before initialization

为什么?因为没有let hoot变量声明。所以错误是说我们不能在声明此函数之前使用它。我们无法在hoot存在之前对其进行访问,这很有意义,但是您可以使用函数声明以及何时使用var。它是JavaScript和letconst的一个有趣的怪癖,可以解决诸如起重之类的意外后果。