【问题标题】:Best practice for declaring empty javascript variables声明空 javascript 变量的最佳实践
【发布时间】:2013-06-04 08:18:10
【问题描述】:

在为变量赋值之前在 javascript 中声明变量是否有类似的最佳实践?有时出于范围原因需要,但如果范围无关紧要怎么办?

// Declare first
(function() {
    var foo = 'bar',
        a = 500,
        b = 300,
        c;

    // Some things get done here with a and b before c can use them...

    c = a * b;    

    // c is now ready to use...
    doSomething(c);
}());

// Declare when needed
(function() {
    var foo = 'bar',
        a = 500,
        b = 300;

    // Some things get done here with a and b before c can use them...

    var c = a * b; 

    // c is now ready to use...
    doSomething(c);
}());

我也想知道对于类似对象文字的最佳实践是什么:

// Add property with null assigned to it
var myObj = {
    foo: null,

    doSomething: function() {
        this.foo = 'bar';
    }
};

// Property gets added when value is set
var myObj = {
    doSomething: function() {
        this.foo = 'bar';
    }
};

【问题讨论】:

  • 主要是风格问题。 Crockford 建议在作用域的顶部声明所有变量,这有时有助于消除一些常见的误解(例如,for 循环内的var 声明实际上属于for 之外的作用域)。
  • @FabrícioMatté 谢谢!甚至没有想过 for 循环,但它确实有道理。

标签: javascript


【解决方案1】:

这主要是风格问题。

由于var 声明自动将hoisted up 放在作用域的顶部,因此将它们放在作用域的顶部是有意义的,这样您就可以更接近解释器的执行方式来阅读代码。

在其作用域的顶部声明变量是Crockford's recommendation。它确实很有意义,因为它消除了一些常见的误解。

例如:

for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);
    }, 0);
}

由于var 具有函数范围,所有迭代(以及其中的函数)都引用相同的i。由于三个定时函数都会在循环结束后执行,所以上面的sn-p会记录3 3次。

现在对于那些有块作用域经验的人来说,上述行为并不是很清楚。重写sn-p:

var i;
for (i = 0; i < 3; i++) {
    // ...
}

现在,i 在全局范围内声明,与之前的 sn-p 完全相同。但是,这一点要清楚得多。


另一个误解:

(function() {
    if (true) {
        var foo = 1;
    } else {
        var foo = 1;
    }
}());

同样,在块范围的语言中¹,上述内容是完全有效的。但是,由于var 声明在解析时被提升到当前函数作用域的顶部,所以上面的内容相当于:

(function() {
    var foo;
    var foo;
    if (true) {
        foo = 1;
    } else {
        foo = 1;
    }
}());

变量被声明了两次。大多数浏览器会忽略第二个声明,代码会“工作”,但静态代码分析工具(如JSHint)会骂你。

你可以只用一个声明重写它,它是完全有效的:

(function() {
    if (true) {
        var foo = 1;
    } else {
        foo = 1;
    }
}());

但是像我这样的强迫症患者会觉得它很丑。同样,在范围顶部声明:

(function() {
    var foo;
    if (true) {
        foo = 1;
    } else {
        foo = 1;
    }
}());

看起来更整洁。


同样,这主要是风格问题。就个人而言,如果我有一个巨大的函数,我讨厌一直向上滚动只是为了检查一个变量是否已经声明并将其添加到列表中。在这种情况下,我可能会在函数中间添加几个 var 声明(违反 Crockford 的建议),我个人认为这些声明更易于阅读和维护。

因为这是一个风格问题,所以请确保您的代码尽可能地易于维护和简洁。


另一方面,我承认,就个人而言,我在第一次使用变量时已经开始并主要使用了var 声明。这是语言的一个方面,您可以毫无问题地使用它。

但我也承认,如果我从一开始就遵循 Crockford 的建议,我会少很多麻烦(就像上面显示的误解一样),并且会更快地掌握 JavaScript 的函数作用域方面。


¹ 请注意,JS 1.7 通过let 引入了块作用域变量,但尚未得到广泛支持。

【讨论】:

  • 为了不让问题的另一面过于个人化,我会评论说我自己的代码也不是最易读的。不过,在团队项目中工作时,请尝试定义一些干净合理的标准,确保代码符合这些标准——这将提供更高的可维护性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-26
  • 2018-07-19
相关资源
最近更新 更多