Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/463.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript函数声明和求值顺序_Javascript_Function Declaration - Fatal编程技术网

JavaScript函数声明和求值顺序

JavaScript函数声明和求值顺序,javascript,function-declaration,Javascript,Function Declaration,为什么这些例子中的第一个不起作用,而其他所有的都起作用 // 1 - does not work (function() { setTimeout(someFunction1, 10); var someFunction1 = function() { alert('here1'); }; })(); // 2 (function() { setTimeout(someFunction2, 10); function someFunction2() { alert('here2'); } })

为什么这些例子中的第一个不起作用,而其他所有的都起作用

// 1 - does not work
(function() {
setTimeout(someFunction1, 10);
var someFunction1 = function() { alert('here1'); };
})();

// 2
(function() {
setTimeout(someFunction2, 10);
function someFunction2() { alert('here2'); }
})();

// 3
(function() {
setTimeout(function() { someFunction3(); }, 10);
var someFunction3 = function() { alert('here3'); };
})();

// 4
(function() {
setTimeout(function() { someFunction4(); }, 10);
function someFunction4() { alert('here4'); }
})();

因为在执行对
setTimeout()
的调用时,尚未分配
someFunction1


someFunction3可能看起来类似,但在本例中,由于您将函数包装
someFunction3()
传递给
setTimeout()
,因此对
someFunction3()
的调用直到稍后才会计算。

Javascript的作用域是基于函数的,而不是严格意义上的词法作用域。也就是说

  • Somefunction1是从封闭函数的开始定义的,但是它的内容在赋值之前是未定义的

  • 在第二个示例中,赋值是声明的一部分,因此它“移动”到顶部

  • 在第三个示例中,当定义了匿名内部闭包时,变量就存在了,但直到10秒后才使用它,此时该值已被赋值

  • 第四个例子既有第二个原因,也有第三个原因


    • 这既不是范围问题,也不是关闭问题。问题在于理解声明和表达式之间的关系

      JavaScript代码,因为即使是Netscape的第一个JavaScript版本和Microsoft的第一个JavaScript副本,也会分两个阶段进行处理:

      阶段1:编译-在此阶段,代码被编译成语法树(字节码或二进制代码取决于引擎)

      阶段2:执行-然后解释解析的代码

      函数声明的语法为:

      function name (arguments) {code}
      
      参数当然是可选的(代码也是可选的,但这有什么意义?)

      但是JavaScript也允许您使用表达式创建函数。函数表达式的语法与函数声明类似,只是它们是在表达式上下文中编写的。表达方式如下:

    • =
      符号右侧的任何内容(或对象文字上的
    • 括号中的任何内容
      ()
    • 函数的参数(这实际上已经在第2部分中介绍)
    • 表达式不同于声明是在执行阶段而不是编译阶段处理的。正因为如此,表达的顺序很重要

      因此,澄清一下:


      第一阶段:汇编。编译器看到变量
      someFunction
      已定义,因此它将创建它。默认情况下,创建的所有变量的值均为undefined。请注意,此时编译器还不能赋值,因为这些值可能需要解释器执行一些代码来返回要赋值的值。在这个阶段,我们还没有执行代码

      第二阶段:执行。解释器看到您想要将变量
      someFunction
      传递给setTimeout。确实如此。不幸的是,
      someFunction
      的当前值未定义


      第一阶段:汇编。编译器看到您正在声明一个名为someFunction的函数,因此它创建了它

      阶段2:解释器看到您想要将
      someFunction
      传递给setTimeout。确实如此。
      someFunction
      的当前值是它的编译函数声明


      第一阶段:汇编。编译器看到您声明了一个变量
      someFunction
      ,并创建了它。与前面一样,其值未定义

      第二阶段:执行。解释器将一个匿名函数传递给setTimeout,以便稍后执行。在这个函数中,它看到您正在使用变量
      someFunction
      ,因此它创建了一个变量的闭包。此时,
      someFunction
      的值仍未定义。然后它看到您将一个函数分配给
      someFunction
      。此时,
      someFunction
      的值不再是未定义的。1/100秒后,setTimeout触发并调用someFunction。因为它的值不再是未定义的,所以它可以工作


      案例4实际上是案例2的另一个版本,加入了一些案例3。在点
      someFunction
      被传递给setTimeout时,由于声明它,它已经存在


      补充澄清:


      您可能想知道为什么
      setTimeout(someFunction,10)
      没有在someFunction的本地副本和传递给setTimeout的副本之间创建闭包。答案是JavaScript中的函数参数总是,如果是数字或字符串,则总是通过值传递,或者通过引用传递。因此,setTimeout实际上并没有获取传递给它的变量someFunction(这意味着要创建一个闭包),而是只获取someFunction引用的对象(在本例中是一个函数)。这是JavaScript中最广泛使用的打破闭包(例如在循环中)的机制。

      这听起来像是遵循良好过程避免麻烦的基本情况。在使用变量和函数之前先声明它们,并像这样声明函数:

      function name (arguments) {code}
      
      避免使用var声明它们。这只是草率的,会导致问题。如果你养成了在使用前声明所有内容的习惯,那么你的大部分问题都会很快消失。在声明变量时,我会立即用有效值初始化它们,以确保它们都没有未定义。我还倾向于包含在函数使用全局变量之前检查其有效值的代码。这是防止错误的额外保护措施

      所有这些工作原理的技术细节有点像你玩手榴弹的物理原理。我的简单建议是首先不要玩手榴弹

      在代码开始时,一些简单的声明可能会解决大多数这类问题,但对co
      // 2
      (function() {
      setTimeout(someFunction, 10);
      function someFunction() { alert('here2'); }
      })();
      
      // 3
      (function() {
      setTimeout(function() { someFunction(); }, 10);
      var someFunction = function() { alert('here3'); };
      })();
      
      function name (arguments) {code}