Декларування декількох змінних у 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
jslint стверджує, що другий спосіб є більш справедливим, але я не згоден.
ThatGuy

29
Другий спосіб - мікрооптимізація. Усі декларації var обробляються одразу, а не одна за одною. Це не так вже й важливо в сучасних браузерах / сучасних комп’ютерах.
webnesto

18
@ 0xc0de: Я хотів би бачити доказ декларації всіх змінних в одному операторі як "ефективних". Якщо ви вимірюєте ефективність лише за кілька збережених байтів, можливо, це можливо. Але якщо взяти до уваги читабельність та ремонтопридатність, я думаю, ви побачите, що передчасна оптимізація зазвичай є неправильним шляхом, тим більше, що сучасні браузери збирають та ініціалізують усі змінні в області на пропуск до виконання. Особисто мені здається, що змінні всі оголошені в одному рядку чи операторі, щоб швидко зрозуміти код важче і більше схильних до помилок.
ogradyjd

9
Щодо ефективності, і uglifyjs, і компілятор закриття google автоматично автоматично розрізають послідовні оператори var в одне ціле, перетворюючи цю точку спору (наскільки я можу сказати, YUI цього не зробить, проте я не перевіряв широко).
бхубер

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твердження на область дії для організації. Те, як усі "області" дотримуються подібної схеми, робить код більш читабельним. Крім того, двигун "піднімає" їх усіх до верху в будь-якому випадку. Тому тримання ваших декларацій разом імітує те, що насправді відбуватиметься ближче.


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 varia1 = "привіт світ" \ n, змінний2 = 2 \ n, змінний3 = "як справи" \ n,
змінний4

2
Це синтаксис Haskell Я відчуваю, що якось не рекомендується / звичайна практика в javascript
shamanSK

14

Це лише питання особистої переваги. Немає різниці між цими двома способами, крім кількох байтів, збережених за допомогою другої форми, якщо викреслити пробіл.


Другий економить пару байтів.
Софі Альперт

Бен Альперт: Як ти уявляєш?
Джош Стодола

Якщо ви викресліть пробіл, ніж 'var foo = "привіт", bar = "світ"; " декларація містить менше символів, ніж 'var foo = "привіт"; var bar = "world";' Якщо у вас є популярний сайт, заощадження кількох байт на JS може допомогти (ви також хочете звести до мінімуму імена змінних тощо)
Брайан Кемпбелл,

Я вважаю, що наразі збережені байти є невідповідними через зростання мініфікерів JavaScript, зокрема, простий режим Google Closer Compiler (так званий).
Брайан Філд

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, якщо це не var<space>або var<tab>проти <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 змінних.
Кирило Резніков

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 на функцію, тоді простіше налагодити код у цілому. Це може означати, що рядки, де оголошуються змінні, не настільки явні, як це може хотіти.

Я відчуваю, що компроміс того вартий, якщо це означає відлучення розробника від відмови від "вару" де завгодно.

Люди можуть скаржитися на 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

Ще одна причина, щоб уникнути версії одного оператора (single var ) - це налагодження. Якщо в будь-якому з рядків присвоєння викинуто виняток, слід стека показує лише один рядок.

Якщо у вас було визначено 10 змінних із синтаксисом комами, у вас немає способу безпосередньо знати, хто з них був винуватцем.

Індивідуальна версія твердження не зазнає цієї неоднозначності.


2

Поняття "Згуртованість над сполученням" може бути застосоване більш загально, ніж просто об'єкти / модулі / функції. Він також може послужити в цій ситуації:

Другий приклад, запропонований ОП, поєднав усі змінні в одне і те ж твердження, що унеможливлює взяти один з рядків і перемістити його кудись інше, не порушуючи речі (високе з'єднання). Перший приклад, який він наводить, робить призначення змінних незалежними один від одного (низьке з'єднання).

"Низьке з'єднання часто є ознакою добре структурованої комп'ютерної системи та гарного дизайну, а в поєднанні з високою згуртованістю підтримує загальні цілі високої читабельності та ремонтопридатності".

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

Тому вибирайте перший.


1
Я не бачу, як це пов'язано з зв'язком або згуртованістю. Хочете допрацювати?
Едсон Медіна

Другий приклад, запропонований ОП, з'єднав усі змінні в одне і те ж твердження, що унеможливлює взяти один з рядків і перемістити його кудись інше, не порушуючи речі (високе з'єднання). Перший приклад, який він наводить, робить призначення змінних незалежними один від одного (низьке з'єднання).
Магне

З'єднання полягає у взаємозалежності між різними модулями / об'єктами / функціями, а не рядками коду!
Едсон Медіна

1
Спочатку мова йшла про модулі, так, але концепцію можна застосовувати більш загально, як показує навіть власне включення об'єктів / функцій у визначення.
Магне

2

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

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

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

Я використовую це форматування строго як особисті переваги. Я, звичайно, пропускаю цей формат для одиночних декларацій або там, де він просто придушує твори.


1

Я вважаю, що до того, як ми почали використовувати ES6, підхід з єдиною вар-декларацією не був ані хорошим, ані поганим (на випадок, якщо у вас є літери і '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;
        });
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.