函数头的 Javascript 变量声明

Javascript variable declarations at the head of a function

本文关键字:变量 声明 Javascript 函数      更新时间:2023-09-26

有人告诉我,javascript 变量都应该在函数中使用之前出现,这样:

function contrived() {
  var myA, myB;
  myA = 10;
  myB = 20;
  return myA + myB;
}

优先于:

function furtherContrivance() {
  var myA = 10;
  var myB = 20;
  return myA + myB;
}

是这样吗?这是为什么呢?

我想有些人可能更喜欢前一种风格,因为这就是它在内部的工作方式。所有局部变量在函数的整个生存期内都存在,即使您使用 var 在函数中间声明它们也是如此。

函数后面声明变量并没有错,语法方面,它可能只是令人困惑,因为变量将存在于声明它们的行之前。因此,此函数:

function bar() {
    alert(foo); // Alerts "undefined". Not an error because the variable does exist.
    var foo = 10;
    alert(foo); // Alerts the value 10.
}

相当于这个:

function bar() {
    var foo;
    alert(foo);
    foo = 10;
    alert(foo);
}

另一个相关的事实是,嵌套函数定义(使用 function foo() { ... } 完成(也会移动到包含函数的顶部,因此即使调用它们的代码在它们之前,它们也将可用。

在这种情况下,这两者之间没有区别。我会选择:

function furtherContrivance() {
  var myA = 10,
      myB = 20;
  return myA + myB;
}

这在JavaScript中被称为single var pattern

你真正需要注意的是在你的函数开始时定义你的变量。javascript中有一个东西叫做variables hoisting,这意味着函数中使用的变量定义"raise"在顶部。最好用一个例子来描述:

var x = 'global'; // global (bounded to a global object which is window in browsers)
function func() { 
    alert(x); // undefined (you expected 'global', right?)
    var x = 'local';
    alert(x); // local
}
func();

真正发生的事情被称为(如我所说(variables hoisting(x的定义在上面提高(,所以上面的代码实际上与

var x = 'global';
function func() {
    var x; // definition of `x` raised on top (variables hoisting)
    alert(x); // undefined in a local scope
    x = 'local';
    alert(x);
}

javscript 解释器所做的是它查看函数内部,收集本地定义的变量并将它们放在顶部 - 这可能是您应该使用 single var pattern 的一个很好的理由。

是的,变量声明应该位于函数的顶部:

function foo() {
  var a, b;
}

但是,初始化变量可以是声明的一部分:

function foo() {
  var a = 10, b = 20;
}

函数顶部声明所有变量背后的原因是为了避免范围混淆。

下面是一个错误代码的示例:

function foo() {
  var b;
  for (var i = 0; i < 5; i++) {
    var a;
    a = b = i;
    setTimeout(function(){
      console.log(a, b);
    }, 1000);
  }
}

如果您执行代码,它将记录 5 次4, 4,而不是计数。这是因为只有函数充当闭包并引入新的作用域。在 JavaScript 中,函数中的任何var声明都会在函数的开头执行。

这使得上述错误更加明显:

function foo() {
  var a, b, i;
  for (i = 0; i < 5; i++) {
    a = b = i;
    setTimeout(function(){
      console.log(a, b);
    }, 1000);
  }
}

在您给出的示例中,情况绝对不是这样。在像Javascript这样的语言中,它更像是开发人员的偏好,但它不会对结果产生任何影响。

是的,将它们放在顶部。它增加了代码的清晰度。

试试这个例子:

var x = 1;
(function() {
    x++;
    alert( x );  // What will this alert show?
    var x = 'done';
    alert( x );
})();

看起来它应该提醒2,但它会提醒NaN

这是因为变量声明被提升到顶部,但初始化保留在同一个位置。

所以实际发生的是:

var x = 1;
(function() {
    var x;
    x++;
    alert( x );  // What will this alert show? NaN
    x = 'done';
    alert( x );
})();

。这使得NaN意料之中。

为了可读性,它绝对是首选。

但是,Javascript"提升"声明。 提升意味着变量和函数将自动移动到其范围的顶部。 这允许您执行一些操作,例如在声明函数之前使用它:

function myScope()
{
   test();
   function test()
   {
      //...
   }
}

这可能会导致一些混淆,尤其是在声明块范围内的变量时。 例如:

for(var i in foo)
{
   var e = myFunc();
}
e 的

声明将被提升到闭包的顶部,e 将被初始化为 undefined。 这允许一些有趣的非直观情况,例如:

if(!foo) //Will not throw reference error because foo is declared already
{
   var foo = {};
}

因此,无论您如何声明变量,它们都会"向上移动"到函数的顶部。

希望这有帮助!