Deklarowanie wielu zmiennych w JavaScript

334

W JavaScript można zadeklarować wiele zmiennych takich jak to:

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

... lub tak:

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

Czy jedna metoda jest lepsza / szybsza od drugiej?

Steve Harrison
źródło
6
Co do szybszego , używając tego jsperf nie widziałem stałego wzrostu prędkości przy użyciu jednej lub drugiej metody.
Majid Fouladpour

Odpowiedzi:

345

Pierwszy sposób jest łatwiejszy w utrzymaniu. Każda deklaracja jest pojedynczą instrukcją w jednym wierszu, dzięki czemu można łatwo dodawać, usuwać i zmieniać kolejność deklaracji.

W przypadku drugiego sposobu denerwujące jest usunięcie pierwszej lub ostatniej deklaracji, ponieważ zawierają one varsłowo kluczowe i średnik. I za każdym razem, gdy dodajesz nową deklarację, musisz zmienić średnik w starej linii na przecinek.

Jeremy Ruten
źródło
67
Jeśli piszesz kod, który chcesz zminimalizować lub spakować później, drugi sposób pozwala kompresorom (takim jak YUI Compressor) na dostarczenie bardziej zminimalizowanej wersji. Jeśli rozmiar jest brany pod uwagę, proponuję zastosować jak najwięcej sugestii JSLint.
Lane
36
jslint twierdzi, że drugi sposób jest bardziej sprawiedliwy, ale nie zgadzam się.
ThatGuy,
29
Drugi sposób to mikrooptymalizacja. Wszystkie deklaracje var są przetwarzane jednocześnie, a nie pojedynczo. Nie ma to większego znaczenia w nowoczesnych przeglądarkach / nowoczesnych komputerach.
webnesto
18
@ 0xc0de: Chciałbym zobaczyć dowód na zadeklarowanie wszystkich zmiennych w jednej instrukcji jako „wydajne”. Jeśli mierzysz wydajność tylko ze względu na kilka zaoszczędzonych bajtów, to może. Ale jeśli weźmiesz pod uwagę czytelność i łatwość konserwacji, myślę, że przekonasz się, że przedwczesna optymalizacja jest zwykle niewłaściwą drogą, zwłaszcza, że ​​nowoczesne przeglądarki zbierają i inicjalizują wszystkie zmienne w zakresie po przejściu przedwykonawczym. Osobiście uważam, że wszystkie zmienne są zadeklarowane w jednym wierszu lub instrukcji, co sprawia, że ​​szybkie zrozumienie kodu jest trudniejsze i bardziej podatne na błędy.
ogradyjd
9
Jeśli chodzi o wydajność, zarówno uglifyjs, jak i kompilator zamykający google automatycznie zgniatają sekwencyjne instrukcje var w jedną, co czyni ten punkt dyskusyjny (o ile mogę stwierdzić, że YUI tego nie zrobi, jednak nie przeprowadzałem obszernych testów).
bhuber
215

Oprócz łatwości konserwacji, pierwszy sposób eliminuje możliwość tworzenia globalnych zmiennych wypadkowych:

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

Podczas gdy drugi sposób jest mniej wybaczający:

(function () {
var variable1 = "Hello World!" // comma is missed out accidently
    variable2 = "Testing...", // becomes a global variable
    variable3 = 42; // a global variable as well
}());
Kenny Ki
źródło
4
Słuszna uwaga. Jeśli są krótkie, wówczas pisanie na jednej linii pozwoli uniknąć tego problemu: var variable1 = "Hello World!", variable2 = "Testing...", variable3 = 42;. Zaginiony ,rozbije się, ale zgadzam się, że jest ryzykowny
Aram Kocharyan
14
Jeśli używasz trybu ścisłego, i tak nie będziesz w stanie tworzyć takich globali.
Danyal Aytekin
1
Jestem fanem deklarowania wielu zmiennych w jednym wierszu, ponieważ uważam, że wygląda to na czystsze. To powiedziawszy, przypadkowe zadeklarowanie zmiennych globalnych jest prawdziwym niebezpieczeństwem. Podczas wyszukiwania przecieków pamięci natknąłem się na wiele przypadków, w których przypadkowo zadeklarowałem kilka zmiennych globalnych jednocześnie, ponieważ zamiast średnika użyłem średnika.
smabbott,
+1 spędził tylko połowę dnia, a nawet zaczął się zastanawiać, dlaczego między tymi dwiema deklaracjami istnieje nieudokumentowana różnica. Następnie przeczytaj tę odpowiedź, dokładnie sprawdź kod i znalazłem błąd. Potrzebujesz wakacji ...
Giedrius
1
Mój edytor tekstów daje mi, Possible Fatal Errorjeśli przegapię śpiączkę, hurra dla mnie!
33

W organizacji często stosuje się jedno varzdanie na zakres . Sposób, w jaki wszystkie „zakresy” mają podobny wzór, dzięki czemu kod jest bardziej czytelny. Dodatkowo silnik i tak „podnosi” je wszystkie na szczyt. Tak więc utrzymywanie razem swoich deklaracji naśladuje to, co faktycznie stanie się bliżej.

spencer.sm
źródło
6
Możesz przechowywać deklaracje razem, nie zmuszając ich do udostępniania tej samej deklaracji „var”. Rozumiem i akceptuję wyjaśnienia podane w jslint (twój link), ale nie podzielam się wnioskami. Jak wspomniano powyżej, jest to bardziej kwestia stylu niż czegokolwiek innego. W świecie Java (między innymi) zaleca się odwrotność (jedna deklaracja na wiersz) w celu zapewnienia czytelności.
PhiLho,
Bardziej czytelny? Jedynym powodem, dla którego ludzie umieszczają je w jednym wierszu, jest powód, dla którego wspominałeś o JS: JS przenosi wszystkie deklaracje na szczyt. Gdyby tak się nie stało, wszyscy ogłosilibyśmy nasze wojny najbliżej miejsca, w którym są używane.
Danyal Aytekin
@ vol7ron tak nie jest i jest to rażące nieporozumienie ze varstwierdzeniem. jest dokładnie odwrotnie. zobacz dokumentację i ten przykład
jackweirdy 17.09.13
@jackweirdy masz rację i tak było, słaba implementacja lub błąd w starszych przeglądarkach. Od tego czasu usunąłem swój komentarz.
vol7ron 17.09.13
29

Robiąc to w ten sposób, jest o wiele bardziej czytelny:

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

Ale w ten sposób zajmuje mniej miejsca i wierszy kodu:

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

Może być idealny do oszczędzania miejsca, ale pozwól, aby kompresory JavaScript obsługiwały go za Ciebie.

Jason Stackhouse
źródło
15

Może tak

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

Z wyjątkiem zmiany pierwszej lub ostatniej zmiennej, jest łatwa do utrzymania i odczytu.

Joe Nerdan
źródło
6
Zazwyczaj, używając przecinka-pierwszego, średnik przechodzi do nowej linii, aby zapobiec temu problemowi. var zmienna 1 = „witaj świecie” \ n, zmienna2 = 2 \ n, zmienna3 = „jak się masz” \ n,
zmienna4
2
To jest składnia Haskella.
Wydaje
14

To tylko kwestia osobistych preferencji. Nie ma różnicy między tymi dwoma sposobami, poza kilkoma bajtami zapisanymi w drugim formularzu, jeśli usuniesz białe znaki.

Brian Campbell
źródło
Drugi pozwala zaoszczędzić kilka bajtów.
Sophie Alpert
Ben Alpert: Jak się masz?
Josh Stodola
Jeśli usuniesz białe znaki, niż „var foo =" hello ", bar =" world "; ' deklaracja zajmuje mniej znaków niż 'var foo = "hello"; var bar = "world";' Jeśli masz popularną witrynę, zaoszczędzisz kilka bajtów na JS (możesz również zminimalizować nazwy zmiennych itp.)
Brian Campbell
Uważam, że zapisane bajty są obecnie nieistotne z powodu wzrostu liczby skryptów JavaScript, w szczególności (tak zwanego) trybu prostego kompilatora Google Closer Compiler.
Bryan Field
1
@ webnesto nigdy nie ma wydajności ze składni, gdy semantyka składni jest taka sama. Nie można od razu wykonać kodu, ale najpierw go przeanalizować i przeprowadzić analizę semantyczną - tutaj wyrównane są oba style deklaracji.
Esailija,
14

ECMAScript6 introducted destructuring assignment który działa całkiem ładny:

[a, b] = [1, 2] abędzie równy 1i bbędzie równy 2.

Nir Naor
źródło
nie odpowiada na pytanie, ale może być lepszą alternatywą dla obu opisanych podejść.
svarog
1
Myślę, że twoje podejście nie jest naprawdę wykonalne, jeśli masz długie listy zmiennych. Trudno powiedzieć, z którą zmienną jest powiązana wartość, a także nie masz ochrony przed błędami, to przypadek złego scalenia, podczas którego przypadkowo możesz usunąć jeden element z tablicy. Przykład: let [aVar, bVar, cVar, xVar, yVar, zVar] = [10, 20, 30, 40, 50]; Więc osobiście nie polecam tego.
Kirill Reznikov
1
przydatne, jeśli chcesz ustawić wiele zmiennych o takich samych wartościach. Na przykład przy zerowaniu w pętli.
Nick
Tak! tego szukałem. Zwłaszcza jeśli chcesz zdefiniować parę dwuwymiarową lub wartości wielowymiarowe, ale nie tablice.
Eugene Kardash
11
var variable1 = "Hello World!";
var variable2 = "Testing...";
var variable3 = 42;

jest bardziej czytelny niż:

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

Ale robią to samo.

Kevin Crowell
źródło
Zużywa mniej „przestrzeni plików”? Myślę, że musisz coś wyjaśnić.
Josh Stodola
@JoshStodola wygląda dla mnie na tę samą przestrzeń plików. Od tego czasu var<space>jego<space><space><space><space>
WORMSS
@ WORMSS, chyba że jest var<space>lub var<tab>kontra <tab>. Nadal w dużej mierze dyskusyjne.
MPag
9

Użyj przypisania Destrukturyzacji ES6 : Rozpakuje wartości z tablic lub właściwości z obiektów do odrębnych zmiennych.

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

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

Rohit Jindal
źródło
4
To okropny pomysł, szczególnie jeśli musisz przypisać około 10 zmiennych.
Kirill Reznikov
7

Moim jedynym, ale niezbędnym zastosowaniem przecinka jest pętla for:

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

Poszedłem tutaj, aby sprawdzić, czy w JavaScript jest to w porządku.

Nawet widząc, jak działa, pozostaje pytanie, czy n jest lokalne dla funkcji.

To weryfikuje, n jest lokalne:

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");

Przez chwilę nie byłem pewien, przełączając się między językami.

codelion
źródło
7

Chociaż oba są poprawne, użycie drugiego odradza niedoświadczonym programistom umieszczanie instrukcji var w dowolnym miejscu i powodowanie problemów z podnoszeniem. Jeśli na górze funkcji znajduje się tylko jedna zmienna na funkcję, łatwiej jest debugować kod jako całość. Może to oznaczać, że linie, w których zmienne są zadeklarowane, nie są tak wyraźne, jak niektórym się to spodoba.

Uważam, że kompromis jest tego wart, jeśli oznacza to oderwanie programisty od porzucenia „var” w dowolnym miejscu.

Ludzie mogą narzekać na JSLint, ja też, ale wiele z nich jest nastawionych nie na rozwiązywanie problemów z językiem, ale na korygowanie złych nawyków programistów, a tym samym zapobieganie problemom w pisanym kodzie. W związku z tym:

„W językach z zakresem blokowym zwykle zaleca się deklarowanie zmiennych w miejscu pierwszego użycia. Ponieważ JavaScript nie ma zakresu blokowego, mądrzej jest zadeklarować wszystkie zmienne funkcji na górze funkcji. zaleca się stosowanie jednej funkcji var dla każdej funkcji. ” - http://www.jslint.com/lint.html#scope

Wade Harrell
źródło
6

Myślę, że to kwestia osobistych preferencji. Wolę to zrobić w następujący sposób:

   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
źródło
6

Kolejnym powodem, dla którego należy unikać wersji z pojedynczą instrukcją (single var ), jest debugowanie. Jeśli jest wyjątek w dowolny z linii przypisania ślad stosu pokazuje tylko jedną linię.

Jeśli zdefiniowano 10 zmiennych za pomocą składni przecinków, nie można bezpośrednio wiedzieć, który z nich był winowajcą.

Indywidualna wersja oświadczenia nie cierpi z powodu tej dwuznaczności.

Shawn
źródło
2

Pojęcie „spójności nad sprzężeniem” może być stosowane bardziej ogólnie niż tylko obiekty / moduły / funkcje. Może również służyć w tej sytuacji:

Drugi przykład, który zasugerował OP, połączył wszystkie zmienne w tę samą instrukcję, co uniemożliwia pobranie jednej z linii i przeniesienie jej gdzie indziej bez zerwania rzeczy (wysokie sprzężenie). Pierwszy podany przez niego przykład uniezależnia przypisania zmiennych (niskie sprzężenie).

„Niskie sprzężenie jest często oznaką dobrze skonstruowanego systemu komputerowego i dobrego projektu, a w połączeniu z wysoką spójnością wspiera ogólne cele wysokiej czytelności i łatwości konserwacji”.

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

Więc wybierz pierwszy.

Magne
źródło
1
Nie rozumiem, jak to się wiąże ze sprzężeniem lub spójnością. Możesz rozwinąć temat?
Edson Medina
Drugi przykład, który zasugerował OP, połączył wszystkie zmienne w tę samą instrukcję, co uniemożliwia pobranie jednej z linii i przeniesienie jej gdzie indziej bez zerwania rzeczy (wysokie sprzężenie). Pierwszy podany przez niego przykład uniezależnia przypisania zmiennych (niskie sprzężenie).
Magne
Sprzężenie dotyczy współzależności między różnymi modułami / obiektami / funkcjami, NIE wierszy kodu!
Edson Medina
1
Pierwotnie chodziło o moduły, tak, ale koncepcję można zastosować bardziej ogólnie, jak pokazuje nawet własne włączenie obiektów / funkcji do definicji.
Magne
2

Stary post, wiem, ale aby dodać mały szczegół perspektywy dla innych pracowników Google:

Kwestię łatwości konserwacji można dość łatwo rozwiązać za pomocą niewielkiego formatowania.

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

Używam tego formatowania wyłącznie w celu osobistych preferencji. Oczywiście pomijam ten format w przypadku pojedynczych deklaracji lub tam, gdzie po prostu działa.

Amant
źródło
1

Wierzę, że zanim zaczęliśmy używać ES6, podejście z deklaracją pojedynczego var nie było ani dobre, ani złe (w przypadku, gdy masz kłaczki i 'use strict'. To było naprawdę preferencje smakowe. Ale teraz wszystko się zmieniło. Są moje przemyślenia na korzyść deklaracji wielowierszowej :

  1. Teraz mamy dwa nowe rodzaje zmiennych i varstało się nieaktualne. Dobrą praktyką jest stosowanie constwszędzie, dopóki naprawdę nie potrzebujesz let. Tak często twój kod będzie zawierał deklaracje zmiennych z przypisaniem w środku kodu, a ze względu na zakres bloków dość często przenosisz zmienne między blokami w przypadku niewielkich zmian. Myślę, że bardziej przekonujące jest robienie tego z deklaracjami wieloliniowymi.

  2. Składnia ES6 stała się bardziej zróżnicowana, otrzymaliśmy destruktory, ciągi szablonów, funkcje strzałek i opcjonalne przypisania. Kiedy mocno używasz wszystkich tych funkcji z deklaracjami pojedynczego var, szkodzi to czytelności.

Kirill Reznikov
źródło
0

Myślę, że najlepszy jest pierwszy sposób (wiele zmiennych), ponieważ w przeciwnym razie możesz skończyć z tym (z aplikacji korzystającej z Knockout), co moim zdaniem jest trudne do odczytania:

    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
źródło