Pytanie o zmienną globalną

0

Cały kod tworzę wewnątrz funkcji jquery

$(document).ready(function()
{

});

Jak powszechnie wiadomo stosowanie zmiennych globalnych to zło. Zastanawia mnie tylko czy jeżeli zadeklaruje sobie wewnątrz tej funkcji jakieś zmienne widziane w całym bloku tej funkcji np. tak

$(document).ready(function()
{
   var JakasZmienna;

  $(".container").click(function()
{
 //jakiś kod
});

function JakasFunkcja()
{

}

});

To czy jest to zła praktyka programistyczna? Czy należąłoby działać tak aby zmienna o nazwie JakasZmienna była ukryta w bloku jakiejś funkcji, domknięcia czy może czegoś innego?

1

globalizm tej zmiennej to tylko połowa problemu, bo owszem, robiąc zmienną globalną wciskasz się z butami w globalną przestrzeń nazw i jeśli inna aplikacja będzie używała tej samej zmiennej, to może ci się posypać program. Ukrywając ją w domknięciu faktycznie ją ukrywasz.

Ale to tylko połowa problemu, bo dalej zostaje stan współdzielony ("shared mutable state is the root of all evil", ja to mówią).

Jeśli masz zmienną globalną, i jeśli każda funkcja zmienia tę zmienną kiedy chce i każda funkcja czyta tę zmienną kiedy chce, i wiele funkcji uzależnia logikę od tej ciągle zmieniającej się zmiennej, to będzie ci ciężko zapanować nad tym, co się dzieje w programie. Z perspektywy aplikacji to jest to samo, bo nawet jeśli masz tą zmienną schowaną przed innymi aplikacjami, to dla ciebie jest ona globalna.

Zmienne, które się nie zmieniają (stałe) są trochę lepsze, ale tylko trochę, bo dalej ileś funkcji będzie zależne od takiej zmiennej globalnej, co też może utrudnić potem jakiekolwiek przeróbki programu.

Czy należąłoby działać tak aby zmienna o nazwie JakasZmienna była
ukryta w bloku jakiejś funkcji, domknięcia czy może czegoś innego?

Jeśli możesz. Jednak nie zawsze się tak da, i czasem musisz przekazać jakieś wartości z jednej funkcji do drugiej. Wtedy masz do wyboru:

  • tworzenie zmiennej globalnej, czyli jest to zło, z powodu, o którym pisałem
  • przekazywanie wartości jako argumentów do funkcji albo zwracanie czegoś w postaci return - również jest to zło, ponieważ jeśli masz wiele funkcji i przekazujesz do każdej jakieś argument, czy pobierasz jakieś wartości z innych funkcji - to też bardzo łatwo ci się zrobi burdel w aplikacji, i możesz się nie połapać, która funkcja zależy od której.

Czyli zawsze będziesz musiał zrobić jakieś zło. W zasadzie w każdej większej aplikacji czyni się "zło" po to, żeby coś osiągnąć dobrego. ;)

Pytanie tylko, w jakiej sytuacji co będzie lepsze? Najlepiej po prostu zastosować jakąś technikę do maximum.

Jak powszechnie wiadomo stosowanie zmiennych globalnych to zło.

czyli np. jeśli nie wiesz, dlaczego stosowanie zmiennych globalnych to zło, to powinieneś napisać program, który by stosował tylko zmienne globalne, i wtedy zobaczysz, że jest to do d**y.

Ale z drugiej strony warto też poprogramować odwrotnie - czyli nie masz żadnych zmiennych globalnych, tylko z setkę funkcji i wszystkie wartości podajesz jako argumenty do funkcji. I walają ci się zmienne lokalne po całej aplikacji. Cieżko w takiej sytuacji zapanować nad "big picture", załapać obraz tego, co się dzieje tak ogólnie w twojej aplikacji. Dobrym przykładem są aplikacje w AngularJS czy React, które przesyłają przez pół aplikacji jaką zmienną do kolejnych komponentów (dlatego powstały takie rzeczy jak Redux albo Mobx, które pozwalają na stosowanie w React zmiennych globalnych* ale w taki sposób, żeby zniwelować wady zmiennych globalnych. Bo używając takich bibliotek jak coś zmienisz to od razu wszystkie zależne komponenty będą wiedzieć, że coś zmieniłeś i się uaktualnią. Ale z drugiej strony te biblioteki też są do d**y, przynajmniej Redux, z Mobx nie korzystałem).

* czy raczej zmiennych reprezentujących "globalny mutowalny stan", bo sama zmienna nie musi być wcale globalna (bo może być np. wstrzykiwana do komponentów w magiczny sposób).

0

Hmmm...Co byś zatem doradził w następującej sytuacji.

Użytkownik widzi listę produktów w tabelce. Jedna z komórek zawiera zdjęcie. Założenie jest takie, że po kliknięciu w to zdjęcie użytkownik może je zmienić poprzez okienko dialogowe.

Po kliknięciu na zdjęcie do zmiennej globalnej(nazwałem ją Sender) jest przypisywany element DOM który wywołał zdarzenie. Konkretnie event.target. Ta sama funkcja wywołuje zdarzenie click ukrytego i niewidocznego elementu <input type="file"> . Wyświetla się okienko dialogowe, użytkownik wybiera plik.

Wybór użytkownika uruchamia funkcję która została podpięta pod wydarzenie change elementu <input type="file">. Jeżeli wszystko jest w porządku i wybrano plik graficzny to należy zmienić właściwość backgroundImage elementu na który kliknął użytkownik i do tego używam tej zmiennej globalnej(o nazwie Sender).

0

W sumie chyba już sobie poradziłem. Przecież funkcje w JS to też obiekty. Wystarczy do obiektu funkcji dopisać jakieś property i nadać mu wartość którą chcemy przechować.

0

No ale to tylko kosmetyka, zamknąłeś tą zmienną w jakiejś przestrzeni nazw, ale nadal korzystasz z niej jak ze zmiennej globalnej.

0

No ale teraz ryzyko konfliktu nazw zostało radykalnie zredukowane prawda? Jakie są szanse, że inna aplikacja, skrypt używa funkcji o tej samej nazwie i jeszcze ma tak samo nazwane property....

0

No przecież napisałem zamknąłeś tą zmienną w jakiejś przestrzeni nazw, zresztą skoro miałeś już kod w $(document).ready(function() { // ... }) to niewiele poprawiłeś (a zaśmieciłeś funkcję propsem, którego nie powinna mieć).

0

To w takim razie to rozwiązanie jest o.k czy nie? Jeśli nie to dlaczego?

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0