在JavaScript中声明多个变量


333

在JavaScript中,可以这样声明多个变量:

var variable1 = "Hello World!";
var variable2 = "Testing...";
var variable3 = 42;

...或像这样:

var variable1 = "Hello World!",
    variable2 = "Testing...",
    variable3 = 42;

一种方法比另一种方法更好/更快吗?


6
至于更快,使用这种jsperf,我看不到使用一种方法或另一种方法获得一致的速度提升
Majid Fouladpour 2014年

Answers:


344

第一种方法更易于维护。每个声明都是在一行上的单个语句,因此您可以轻松地添加,删除和重新排列声明。

使用第二种方法时,删除第一个或最后一个声明很烦人,因为它们包含var关键字和分号。每次添加新的声明时,都必须将旧行中的分号更改为逗号。


67
如果编写的代码希望以后缩小或打包,则第二种方法允许压缩程序(例如YUI Compressor)为您提供更缩小的版本。如果考虑大小,那么我建议尽可能遵循JSLint的建议。

36
jslint声称第二种方式更合理,但我不同意。
ThatGuy

29
第二种方法是微优化。所有的var声明都被一次处理,而不是一次处理。在现代浏览器/现代计算机中,这无关紧要。
webnesto 2012年

18
@ 0xc0de:我想看到在一个语句中将所有变量声明为“有效”的证明。如果您仅根据节省的几个字节来衡量效率,那么也许可以。但是,如果考虑到可读性和可维护性,我认为您会发现过早优化通常是错误的方法,特别是因为现代浏览器会在执行前通过收集和初始化作用域中的所有变量。就个人而言,我发现所有变量都在单行或语句中声明,以使快速理解代码变得更加困难,并且更容易出错。
ogradyjd 2013年

9
关于效率,uglifyjs和Google闭包编译器都会自动将顺序var语句压缩为一个,从而使这一点变得毫无意义(据我所知,YUI不会这样做,但是我尚未进行广泛测试)。
bhuber 2014年

215

除了可维护性之外,第一种方法消除了事故全局变量创建的可能性:

(function () {
var variable1 = "Hello World!" // semicolon is missed out accidently
var variable2 = "Testing..."; // still a local variable
var variable3 = 42;
}());

虽然第二种方法不太宽容:

(function () {
var variable1 = "Hello World!" // comma is missed out accidently
    variable2 = "Testing...", // becomes a global variable
    variable3 = 42; // a global variable as well
}());

4
好点子。如果它们很短,那么在一行上写就可以避免此问题:var variable1 = "Hello World!", variable2 = "Testing...", variable3 = 42;。失踪人员,将坠毁,但我同意这是有风险的
Aram Kocharyan'1

14
如果您使用严格模式,则无论如何都将无法创建这样的全局变量。
Danyal Aytekin

1
我喜欢在一行上声明多个变量,因为我认为它看起来更干净。也就是说,意外声明全局变量是真正的危险。在寻找内存泄漏时,我遇到了多个实例,在这些实例中我不小心一次声明了几个全局变量,因为我使用了分号而不是逗号。
smabbott 2013年

+1只是花了半天的时间,甚至开始想知道为什么这两个声明之间存在未记录的差异。然后阅读此答案,仔细检查代码,发现错误。需要放假...
Giedrius 13'Apr

1
Possible Fatal Error如果我想念昏迷,我的文字编辑器会给我一个提示,请为我加油!

33

在组织的每个范围中通常只使用一个var语句。所有“作用域”遵循相似模式的方式使代码更具可读性。此外,引擎无论如何都将它们“提升”到顶部。因此,将您的声明放在一起可以模仿实际上会发生的事情。


6
您可以将声明保持在一起,而不必使它们共享相同的“ var”声明。我理解并接受jslint(您的链接)给出的解释,但我不同意结论。如上所述,最重要的是风格。在Java世界(以及其他世界)中,建议为了提高可读性(每行一个声明)。
PhiLho 2011年

更具可读性?人们将它们放在一行上的唯一原因是您提到的特定于JS的原因:JS将所有声明移到顶部。如果它不这样做,我们所有人都将声明我们的变量最接近使用它们的地方。
Danyal Aytekin

@ vol7ron并非如此,这是对该var声明的严重误解。恰恰相反。请参阅文档此示例
jackweirdy 2013年

@jackweirdy您是正确的,确实是这种情况,实施不佳或旧版浏览器中的错误。此后,我删除了我的评论。
vol7ron

29

这样做的话,可读性更高:

var hey = 23;
var hi = 3;
var howdy 4;

但是这种方式占用的空间和代码行更少:

var hey=23,hi=3,howdy=4;

它可能是节省空间的理想选择,但是让JavaScript压缩器为您处理它。


15

也许是这样

var variable1 = "hello world"
, variable2 = 2
, variable3 = "how are you doing"
, variable4 = 42;

除了更改第一个或最后一个变量时,它易于维护和读取。


6
通常,使用逗号优先,分号会换行以防止出现此问题。var variable1 =“ hello world” \ n,variable2 = 2 \ n,variable3 =“你好吗” \ n,variable4 = 42 \ n; \ n
BrianFreud

2
这是Haskell语法。我觉得在JavaScript,不知怎的,不建议/常见的做法
shamanSK

14

这只是个人喜好问题。这两种方式没有什么区别,除了如果删除空白,第二种形式会节省一些字节。


第二个保存几个字节。
苏菲·阿尔珀特2009年

本·阿尔珀特:您如何看待?
乔什·斯托多拉

如果除去空格,则比'var foo =“ hello”,bar =“ world”;' 声明占用的字符少于'var foo =“ hello”; var bar =“ world”;' 如果您有一个受欢迎的网站,则在JS上保存一些字节可以有所帮助(您还希望最小化变量名,等等)
Brian Campbell,2009年

由于JavaScript压缩程序(特别是Google Closer编译器(所谓的)简单模式)的兴起,我目前认为保存的字节无关紧要。
布赖恩·菲尔德

1
当语法的语义相同时,@ webnesto不会对语法产生任何影响。不会立即执行代码,而是先对其进行解析并进行语义分析-这是两种声明样式均等的地方。
Esailija

14

ECMAScript6引入了分解工作,该工作相当不错:

[a, b] = [1, 2] a将等于1b将等于2


它不能回答问题,但是可以更好地替代上述两种方法。
svarog

1
我认为,如果变量列表很长,那么您的方法实际上是不可行的。很难说出哪个值与哪个变量相关,并且您没有错误保护措施是合并错误的情况,在此期间您可能会意外地从数组中删除一个元素。示例: let [aVar, bVar, cVar, xVar, yVar, zVar] = [10, 20, 30, 40, 50]; 因此,我个人不建议这样做。
基里尔·雷兹尼科夫

1
如果您想设置很多具有相同值的变量,则非常方便。例如,用于在循环中重置为零。
尼克

是! 这就是我想要的。特别是如果要定义二维对或多维值,而不是数组。
Eugene Kardash '19

11
var variable1 = "Hello World!";
var variable2 = "Testing...";
var variable3 = 42;

比以下内容更具可读性:

var variable1 = "Hello World!",
    variable2 = "Testing...",
    variable3 = 42;

但是他们做同样的事情。


使用较少的“文件空间”?我认为您需要做一些解释。
乔什·斯托多拉

@JoshStodola在我看来是相同的文件空间。而不是因为var<space><space><space><space><space>
WORMSS

@WORMSS除非它是var<space>var<tab>VS <tab>。仍然在很大程度上没有定论。
mpag

9

使用ES6解构 分配:将数组中的值或对象中的属性解压缩为不同的变量。

let [variable1 , variable2, variable3] = 
["Hello World!", "Testing...", 42];

console.log(variable1); // Hello World!
console.log(variable2); // Testing...
console.log(variable3); // 42


4
这是一个糟糕的主意,尤其是当您需要分配大约10个变量时。
基里尔·雷兹尼科夫'18

7

我唯一但必不可少的逗号用法是在for循环中:

for (var i = 0, n = a.length; i < n; i++) {
  var e = a[i];
  console.log(e);
}

我去这里查看在JavaScript中是否可以。

即使看到它起作用,仍然存在一个问题,即n是否在函数本地。

这验证n是本地的:

a=[3,5,7,11];
(function l () { for (var i = 0, n = a.length; i < n; i++) {
  var e = a[i];
  console.log(e);
}}) ();
console.log(typeof n == "undefined" ?
  "as expected, n was local" : "oops, n was global");

有一阵子我不确定,是否在语言之间切换。


7

尽管两者都是有效的,但使用第二种方法可以阻止缺乏经验的开发人员将var语句放在各处,并引起提升问题。如果每个函数只有一个var,则在函数顶部,则更容易对整个代码进行调试。这可能意味着声明变量的行并不像某些人希望的那样明确。

我认为,权衡是值得的,如果这意味着要让开发人员放弃在他们喜欢的任何地方放弃“ var”。

人们也可能抱怨JSLint,我也这样做,但是很多它不是为了解决语言问题,而是为了纠正编码人员的不良习惯,从而防止他们编写的代码出现问题。因此:

“在具有块范围的语言中,通常建议在首次使用的位置声明变量。但是,由于JavaScript没有块范围,因此在函数顶部声明所有函数变量是比较明智​​的。建议每个函数使用一个var语句。” - http://www.jslint.com/lint.html#scope


6

我认为这是个人喜好问题。我更喜欢通过以下方式:

   var /* Vars */
            me = this, that = scope,
            temp, tempUri, tempUrl,
            videoId = getQueryString()["id"],
            host = location.protocol + '//' + location.host,
            baseUrl = "localhost",
            str = "Visit W3Schools",
            n = str.search(/w3schools/i),
            x = 5,
            y = 6,
            z = x + y
   /* End Vars */;

6

避免使用单语句版本(单个var)的另一个原因是调试。如果在任何分配行中引发了异常,则堆栈跟踪仅显示一行。

如果您有10个用逗号语法定义的变量,则您将无法直接知道哪个是罪魁祸首。

单个语句版本不会遭受这种歧义。


2

“耦合之上的内聚”的概念不仅可以用于对象/模块/功能,还可以更普遍地应用。它也可以在这种情况下使用:

OP建议的第二个示例将所有变量都耦合到同一条语句中,这使得不可能采用其中的一行并将其移动到其他位置而不会破坏东西(高度耦合)。他给出的第一个示例使变量分配彼此独立(低耦合)。

“低耦合通常是结构良好的计算机系统和良好设计的标志,并且与高凝聚力结合使用时,可以达到较高的可读性和可维护性的总体目标。”

http://en.wikipedia.org/wiki/Coupling_(computer_programming)

因此,选择第一个。


1
我看不到这与耦合或凝聚力有什么关系。关心详细吗?
埃德森·麦地那

OP建议的第二个示例将所有变量都耦合到同一条语句中,这使得不可能采用其中的一行并将其移动到其他位置而不会破坏东西(高度耦合)。他给出的第一个示例使变量分配彼此独立(低耦合)。
Magne

耦合是关于不同模块/对象/功能之间的相互依赖性,而不是代码行!
埃德森·麦地那

1
最初它是关于模块的,是的​​,但是这个概念可以更广泛地应用,因为甚至您自己将对象/功能包含在定义中也是如此。
Magne

2

我知道是一篇旧文章,但为Google同事们添加了一些观点上的细节:

只需使用少量格式即可轻松解决可维护性问题。

let
  my_var1 = 'foo',
  my_var2 = 'bar',
  my_var3 = 'baz'
;

我严格按照个人喜好使用这种格式。当然,我跳过了这种格式,只声明了一个声明,或者只是简单地修饰了作品。


1

我相信,在我们开始使用ES6之前,使用单个var声明的方法既不好也不坏(如果您有短绒棉和'use strict'。这确实是口味偏好。但是现在情况对我来说已经改变了。我有想法支持多行声明) :

  1. 现在,我们有了两种新的变量,并且var已经过时了。最好const在您真正需要的地方使用它let。因此,您的代码经常会在代码中间包含变量声明和赋值,并且由于块作用域的限制,在进行较小更改的情况下,您经常会在块之间移动变量。我认为使用多行声明更方便。

  2. ES6语法变得更加多样化,我们有了析构函数,模板字符串,箭头函数和可选的附件。当您在单个var声明中大量使用所有功能时,会损害可读性。


0

我认为第一种方式(多个vars)是最好的,因为您最终可能会以这种方式(使用Knockout的应用程序)结束这种方式,我认为这很难理解:

    var categories = ko.observableArray(),
        keywordFilter = ko.observableArray(),
        omniFilter = ko.observable('').extend({ throttle: 300 }),
        filteredCategories = ko.computed(function () {
            var underlyingArray = categories();
            return ko.utils.arrayFilter(underlyingArray, function (n) {
                return n.FilteredSportCount() > 0;
            });
        }),
        favoriteSports = ko.computed(function () {
            var sports = ko.observableArray();
            ko.utils.arrayForEach(categories(), function (c) {
                ko.utils.arrayForEach(c.Sports(), function (a) {
                    if (a.IsFavorite()) {
                        sports.push(a);
                    }
                });
            });
            return sports;
        }),
        toggleFavorite = function (sport, userId) {
            var isFavorite = sport.IsFavorite();

            var url = setfavouritesurl;

            var data = {
                userId: userId,
                sportId: sport.Id(),
                isFavourite: !isFavorite
            };

            var callback = function () {
                sport.IsFavorite(!isFavorite);
            };

            jQuery.support.cors = true;
            jQuery.ajax({
                url: url,
                type: "GET",
                data: data,
                success: callback
            });
        },
        hasfavoriteSports = ko.computed(function () {
            var result = false;
            ko.utils.arrayForEach(categories(), function (c) {
                ko.utils.arrayForEach(c.Sports(), function (a) {
                    if (a.IsFavorite()) {
                        result = true;
                    }
                });
            });
            return result;
        });
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.