【问题标题】:The benefits of declaring variables at the top of the function body in JavaScript在 JavaScript 函数体顶部声明变量的好处
【发布时间】:2014-09-20 05:08:13
【问题描述】:

我正在阅读 Douglas Crockford 的书 "Javascript: The Good Parts"。他在谈论范围,并说JS没有块范围:

在许多现代语言中,建议声明变量 尽可能晚,在第一个使用点。原来是这样 对 Javascript 的建议不好,因为它缺少块范围。所以相反,它 最好在顶部声明函数中使用的所有变量 函数体。

但是,我想不出一个很好的例子说明这个陈述为什么有意义,如果能看到一些例子来验证这个陈述,那就太好了。

【问题讨论】:

  • 想想for 在同一范围内循环,使用相同的i 变量。首先声明 i 并重用它似乎更正确或惯用。
  • 如果你用 var 声明它,它将在范围内是本地的。如果不是,它将是全球性的。因此,为了明确 var 是本地的,请在函数开头显式声明它
  • @mplungjan 我理解的问题不在于是否声明变量,而是在函数中声明它们的位置。
  • @Tarik 你问的是变量声明和var 是变量是如何声明的,那么它是一个完全独立的话题吗?
  • JS 中的变量总是在任何事情发生之前被声明。这是由运行时编译器为您完成的。

标签: javascript


【解决方案1】:

在顶部声明变量可以帮助您避免这样的情况:

function outer() {
  var i = 50;

  function inner() {
    alert(i);
    var i= 30;
  }
  inner();
}

outer();

许多人希望警报显示50,看到undefined 他们会感到惊讶。这是因为i 变量在inner 函数中声明,但直到alert 之后才被初始化。因此它具有完整的功能范围,即使它是在首次使用后声明的。

【讨论】:

  • 这是一个简单的例子,但i 是一个常见的循环变量。 C 程序员可能会看到 for(var i = ...) 并错误地认为 i 具有块作用域。在顶部声明变量可能有助于易读性和可维护性,但我不得不承认,我很少在使用前声明循环变量。
  • 澄清一下,这是由于提升,所以函数内部实际上是var i; alert(i); i = 30;
  • 正确。直到我看到@torazaburo 的帖子后才想到“吊装”这个词。
  • 那只是因为你使用了var i = 30;。取下var,你会得到50。当您在函数中使用关键字 var 时,它会将 var 限定为该函数。
  • @Assaf:您的说明非常好。谢谢!
【解决方案2】:

在函数顶部声明变量,以记录在一个地方使用的所有变量。

它还避免了由于有人想象一个变量是块范围的而实际上它不是块范围的而导致的混淆,如下所示:

var i=0;
if (true) {
   var i=1;
}
// what is i? C programmer might imagine it's 0.

如果变量也在声明时被初始化,将声明放在顶部可以避免初始化时间的潜在问题:

console.log(foo);
var foo = 1;

在这种情况下,foo 被提升,因此它在console.log 时声明,但尚未初始化。所以这实际上就像

var foo;
console.log(foo); // no ReferenceError, but undefined
foo = 1;

【讨论】:

  • 我真的很喜欢这个答案。
【解决方案3】:

在我看来,由于 javascript 没有块作用域,因此在函数顶部声明所有变量可以让您更容易发现不必使用的变量,因为您可以重用其他变量。

例子:

function test(){
    var pages = [
        'www.stackoverflow.com',
        'www.google.com'
    ];

    var users = [
        'John',
        'Bob'
    ];

    for (var page = 0; page < pages.length; page++) {
        console.log(pages[page]);
    };

    for (var user = 0; user < users.length; user++) {
        console.log(users[user]);
    };
}

可以改成:

function test(){
    var index, pages, users;

    pages = [
        'www.stackoverflow.com',
        'www.google.com'
    ];

    users = [
        'John',
        'Bob'
    ];

    for (index = 0; index < pages.length; index++) {
        console.log(pages[index]);
    };

    for (index = 0; index < users.length; index++) {
        console.log(users[index]);
    };
}

并从内存中节省一个变量空间。

在这样一个小函数中,重点可能看不到,但想象一个有数千行代码的整个项目。这可能会使您的代码运行得更快。

【讨论】:

  • 您现在不应该从for 循环中删除var 吗?
  • 这可能有点相关,但我仍然认为这不是道格拉斯推荐它的原因。如果是这种情况,那么即使在现代语言中,我们也应该一直这样做。
  • 这里也有一些想法stackoverflow.com/questions/5053073/…
  • 在循环中使用var。如果你的循环在一个函数中,你可能会遇到问题,现在你的增量是全局的。您可能没有考虑并意外地在更高级别的范围内重新定义变量。
【解决方案4】:

这并不总是一个好主意。这取决于你在做什么。当他们说没有必要声明"top level" 变量时,他们的意思是这并不重要。它在函数内部很重要。考虑以下示例:

varOne = 1; varTwo = 2; varThree = 3; // undeclared
function lameFunc(){
  var varOne = 'Something'; // does no affect varOne at the top level
  return varOne;
}

同:

var varOne = 1, varTwo = 2, varThree = 3; // declared
function lameFunc(){
  var varOne = 'Something'; // does no affect varOne at the top level
  return varOne;
}

当然,使用关键字var 更容易查看变量,并且由于"top level" 没有不利影响,因此建议使用。

请注意,当我更改 lameFunc() 时,无论哪种方式,你都会影响更高的杠杆 var。

function lameFunc(){
  /* varOne is effected at the higher level whether or not `var` is declared
    above as in `varOne = 1` or `var varOne = 1` */
  varOne = 'Something';
  return varOne;
}

此外,如果您在事件之外声明一个变量,例如var someInputVal = document.getElementById('someInput').value;,那么假设您想要获取元素的 onclick 值。您可能希望在Element.onclick = function(){/* in here */} 中声明var,因为在您单击Element 之前输入可能已更改。在处理您的事件的函数之外声明var someInput = document.getElementById('someInput'); 可能是可以的,如果元素没有变为undefined,那么您可以访问类似:

var doc = document, bod = doc.body;
function E(e){
  return doc.getElementById(e);
}
var someInput = E('someInput'), someInputVal = someInput.value;
E('clickButton').onclick = function(){
  console.log(someInputVal); // will not be what document.getElementById('someInput').value is if it was changed before clicking
  var declared = someInput.value;
  console.log(declared);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多