Объявление нескольких переменных в JavaScript

334

В JavaScript можно объявить несколько переменных следующим образом:

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

... или так:

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

Один метод лучше / быстрее, чем другой?

Стив Харрисон
источник
6
Что касается более быстрого , используя этот jsperf, я не мог видеть последовательное увеличение скорости, используя один метод или другой.
Маджид Фуладпур

Ответы:

345

Первый способ проще в обслуживании. Каждое объявление - это отдельный оператор в одной строке, поэтому вы можете легко добавлять, удалять и изменять порядок объявлений.

При втором способе раздражает удаление первого или последнего объявления, поскольку они содержат varключевое слово и точку с запятой. И каждый раз, когда вы добавляете новое объявление, вы должны изменить точку с запятой в старой строке на запятую.

Джереми Рутен
источник
67
Если вы пишете код, который ожидаете уменьшить или упаковать позже, второй способ позволяет компрессорам (таким как YUI Compressor) предоставить вам более минимизированную версию. Если размер является соображением, то я бы предложил следовать как можно большему количеству предложений JSLint.
переулок
36
Джлинт утверждает, что второй путь более праведен, но я не согласен.
ThatGuy
29
Второй способ - это микрооптимизация. Все объявления var обрабатываются одновременно, а не по одному. Это не имеет большого значения в современных браузерах / современных компьютерах.
webnesto
18
@ 0xc0de: Я хотел бы видеть доказательство объявления всех переменных в одном утверждении как «эффективных». Если вы измеряете эффективность только на основе нескольких сохраненных байтов, то, возможно,. Но если принять во внимание удобочитаемость и удобство сопровождения, я думаю, вы обнаружите, что преждевременная оптимизация, как правило, является неправильным путем, тем более что современные браузеры собирают и инициализируют все переменные в области видимости на этапе предварительного выполнения. Лично я нахожу наличие переменных, объявленных в одной строке или выражении, чтобы сделать понимание кода более трудным и более подверженным ошибкам.
ogradyjd
9
Что касается эффективности, то и uglifyjs, и компилятор Google Closure автоматически объединят последовательные операторы var в одно, что делает этот вопрос спорным (насколько я могу судить, YUI этого не сделает, однако я не тестировал всесторонне).
bhuber
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;. Пропавший ,пропадет, но я согласен, что это рискованно
Арам Кочарян
14
Если вы используете строгий режим, вы все равно не сможете создавать такие глобальные переменные.
Данял Айтекин
1
Я фанат объявления нескольких переменных в одной строке, потому что я думаю, что это выглядит чище. Тем не менее, случайное объявление глобальных переменных является реальной опасностью. При поиске утечек памяти я сталкивался с несколькими случаями, когда я случайно объявлял сразу несколько глобальных переменных, потому что использовал точку с запятой вместо запятой.
smabbott
+1 просто потратил половину дня и даже начал задумываться, почему между этими двумя декларациями есть недокументированная разница. Затем прочитайте этот ответ, внимательно проверите код и обнаружите ошибку. Нужен праздник ...
Гиедриус
1
Мой текстовый редактор дает мне, Possible Fatal Errorесли я пропущу кому, ура для меня!
33

Обычно для организации используется один varоператор в каждой области . То, как все «области видимости» следуют похожему шаблону, делает код более читабельным. Кроме того, двигатель все равно «поднимает» их наверх. Таким образом, хранение ваших деклараций подражает тому, что будет происходить более тесно.

spencer.sm
источник
6
Вы можете хранить декларации вместе, не делая их общими для одной и той же декларации 'var'. Я понимаю и принимаю объяснения, данные на jslint (ваша ссылка), но я не разделяю заключение. Как сказано выше, это больше вопрос стиля, чем что-либо еще. В мире Java (среди прочего) для удобства чтения рекомендуется обратное (одно объявление на строку).
PhiLho
Более читабельным? Единственная причина, по которой люди помещают их в одну строку, - это причина, по которой вы упомянули JS: JS перемещает все объявления вверх. Если бы этого не произошло, мы бы все объявили наши переменные ближе всего к точке их использования.
Данял Айтекин
@ vol7ron, это не так, и это грубое недопонимание varзаявления. полная противоположность верна. см. документацию и этот пример
jackweirdy
@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 = "Привет, мир" \ n, variable2 = 2 \ n, variable3 = "как дела" \ n, variable4 = 42 \ n; \ n
BrianFreud
2
Это синтаксис Haskell. Я чувствую, что как-то это не рекомендуется / обычная практика в javascript
shamanSK
14

Это просто вопрос личных предпочтений. Нет разницы между этими двумя способами, за исключением нескольких байтов, сохраненных во второй форме, если вы удалите пробел.

Брайан Кэмпбелл
источник
Второй сохраняет пару байтов.
Софи Алперт
Бен Альперт: Как ты фигурируешь?
Джош Стодола
Если вы удалите пробел, тогда 'var foo = "hello", bar = "world";' объявление занимает меньше символов, чем 'var foo = "hello"; var bar = "world";' Если у вас есть популярный сайт, сохранение нескольких байтов в JS может помочь (вы также хотели бы минимизировать имена переменных и т. Д.)
Брайан Кэмпбелл,
Я считаю, что в настоящее время сохраненные байты не имеют значения из-за появления минимизаторов JavaScript, в частности, простого режима (так называемого) компилятора Google Closer.
Брайан Филд
1
@webnesto никогда не бывает никакой производительности от синтаксиса, когда семантика синтаксиса одинакова. Нельзя сразу выполнить код, а сначала проанализировать его и выполнить семантический анализ - вот где оба стиля декларации выровнены.
Esailija
14

ECMAScript6 представил назначение деструктурирования, которое работает довольно хорошо:

[a, b] = [1, 2] aбудет равно 1и bбудет равно 2.

Нир Наор
источник
это не отвечает на вопрос, но может быть лучшей альтернативой обоим описанным подходам.
Сварог
1
Я думаю, что ваш подход не очень эффективен, если у вас длинные списки переменных. Трудно сказать, к какой переменной относится какое значение, а также у вас нет защиты от ошибок, это случай неудачного слияния, во время которого вы могли случайно удалить один элемент из массива. Пример: let [aVar, bVar, cVar, xVar, yVar, zVar] = [10, 20, 30, 40, 50]; Итак, лично я не рекомендую это.
Кирилл Резников
1
удобно, если вы хотите установить множество переменных с одинаковыми значениями. Например, для обнуления в цикле.
Ник
Да! это то, что я искал. Особенно, если вы хотите определить двумерную пару или многомерные значения, но не массивы.
Евгений Кардаш
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>против <tab>. Все еще в значительной степени спорный.
mpag
9

Используйте ES6 Destructuring assignment : он распаковывает значения из массивов или свойства из объектов в отдельные переменные.

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

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

Рохит Джиндал
источник
4
Это ужасная идея, особенно если вам нужно назначить около 10 переменных.
Кирилл Резников
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");

На мгновение я не был уверен, переключаясь между языками.

codelion
источник
7

Хотя оба они действительны, использование второго препятствует неопытным разработчикам размещать операторы 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 */;
v1r00z
источник
6

Еще одна причина, по которой следует избегать использования одной версии оператора (single var ), - отладка. Если исключение выдается в любой из строк присваивания, трассировка стека показывает только одну строку.

Если у вас было 10 переменных, определенных с помощью синтаксиса запятой, у вас нет возможности напрямую узнать, какая из них была виновником.

Индивидуальная версия заявления не страдает от этой двусмысленности.

Shawn
источник
2

Понятие «Сплоченность через сцепление» может применяться более широко, чем просто объекты / модули / функции. Это может также служить в этой ситуации:

Второй пример, предложенный OP, соединил все переменные в одном выражении, что делает невозможным взять одну из строк и переместить ее в другое место, не нарушая вещи (высокая связь). Первый пример, который он привел, делает присвоения переменных независимыми друг от друга (слабая связь).

«Низкая связь часто является признаком хорошо структурированной компьютерной системы и хорошего дизайна, а в сочетании с высокой связностью поддерживает общие цели высокой читаемости и удобства обслуживания».

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

Так что выбирай первый.

Магне
источник
1
Я не вижу, как это связано с сцеплением или сплоченностью. Хотите разработать?
Эдсон Медина
Второй пример, предложенный OP, соединил все переменные в одном выражении, что делает невозможным взять одну из строк и переместить ее в другое место, не нарушая вещи (высокая связь). Первый пример, который он привел, делает присвоения переменных независимыми друг от друга (слабая связь).
Магне
Связывание - это взаимозависимость между различными модулями / объектами / функциями, а НЕ строками кода!
Эдсон Медина
1
Первоначально это было о модулях, да, но концепция может применяться более широко, как показывает даже ваше собственное включение объектов / функций в определение.
Магне
2

Я знаю старый пост, но добавлю небольшую деталь перспективы для коллег-гуглеров:

Проблема с ремонтопригодностью может быть легко решена с помощью небольшого форматирования.

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

Я использую это форматирование строго как личное предпочтение. Я пропускаю этот формат для отдельных объявлений, конечно, или там, где он просто склеивает работы.

кавалер
источник
1

Я считаю, что до того, как мы начали использовать ES6, подход с одиночным объявлением var не был ни хорошим, ни плохим (в случае, если у вас есть линтеры и 'use strict'. Это было действительно вкусовое предпочтение. Но теперь все изменилось для меня. Есть мои мысли в пользу многострочного объявления :

  1. Теперь у нас есть два новых типа переменных, и они varустарели. constПолезно использовать везде, где вам действительно нужно let. Поэтому довольно часто ваш код будет содержать объявления переменных с назначением в середине кода, и из-за видимости блока вы часто будете перемещать переменные между блоками в случае небольших изменений. Я думаю, что это более удобно делать с многострочными декларациями.

  2. Синтаксис ES6 стал более разнообразным, мы получили деструкторы, строки шаблонов, функции стрелок и необязательные назначения. Когда вы интенсивно используете все эти функции с одиночными объявлениями var, это ухудшает читабельность.

Кирилл Резников
источник
0

Я думаю, что первый способ (несколько переменных) лучше, так как в противном случае вы можете получить это (из приложения, использующего 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;
        });
vegemite4me
источник