Jak zadeklarować zmienną globalną w pliku .js.

86

Potrzebuję kilku zmiennych globalnych, których potrzebuję we wszystkich .jsplikach.

Na przykład rozważ następujące 4 pliki:

  1. global.js
  2. js1.js
  3. js2.js
  4. js3.js

Czy istnieje sposób, w jaki mogę zadeklarować 3 zmienne globalne w programie global.jsi uzyskać do nich dostęp w dowolnym z pozostałych 3 .jsplików, biorąc pod uwagę, że załaduję wszystkie powyższe 4 pliki do dokumentu HTML?

Czy ktoś może mi powiedzieć, czy jest to możliwe, czy też jest jakiś sposób, aby to osiągnąć?

kp11
źródło

Odpowiedzi:

96

Po prostu zdefiniuj swoje zmienne w global.js poza zakresem funkcji:

// global.js
var global1 = "I'm a global!";
var global2 = "So am I!";

// other js-file
function testGlobal () {
    alert(global1);
}

Aby upewnić się, że to zadziała, musisz dołączyć / link do global.js przed próbą uzyskania dostępu do jakichkolwiek zmiennych zdefiniowanych w tym pliku:

<html>
    <head>
        <!-- Include global.js first -->
        <script src="/YOUR_PATH/global.js" type="text/javascript"></script>
        <!-- Now we can reference variables, objects, functions etc. 
             defined in global.js -->
        <script src="/YOUR_PATH/otherJsFile.js" type="text/javascript"></script>
    </head>
    [...]
</html>

Możesz oczywiście umieścić link w tagach skryptu tuż przed zamykającym tagiem <body>, jeśli nie chcesz, aby ładowanie plików js przerywało początkowe ładowanie strony.

PatrikAkerstrand
źródło
4
Chociaż ta odpowiedź jest prawidłowa, zalecałbym Ci określanie zakresu zmiennych Google Javascript, aby uzyskać lepsze zrozumienie i prawdopodobnie unikać robienia rzeczy dokładnie w ten sposób.
aleemb
1
Zgoda. Zawsze staram się uwzględniać wszystkie funkcje i zmienne we wspólnej „przestrzeni nazw”, aby uniknąć bałaganu i konfliktów. Zwykle nazywam to skrótem projektu lub firmy.
PatrikAkerstrand
Odrzucenie tej odpowiedzi i innych podobnych, ponieważ zakłada, że ​​zmienna globalna zostanie utworzona w zakresie globalnym, a także wymaga, aby pierwsza wzmianka o zmiennej znajdowała się w zakresie globalnym przed wszystkimi innymi wzmiankami.
Andrew
1
@Andrew Ta odpowiedź została napisana osiem lat temu. Pod każdym względem było wtedy słuszne. Jeśli naprawdę chcesz coś zrobić, możesz zamiast tego zaproponować zmianę?
PatrikAkerstrand
@PatrikAkerstrand Randki właściwie nie mają znaczenia. Inne odpowiedzi, które używają obiektu globalnego, są wystarczające; Wyjaśniłem, dlaczego tak nie jest.
Andrew,
89

Zalecane podejście to:

window.greeting = "Hello World!"

Następnie możesz uzyskać do niego dostęp w dowolnej funkcji:

function foo() {

   alert(greeting); // Hello World!
   alert(window["greeting"]); // Hello World!
   alert(window.greeting); // Hello World! (recommended)

}

Takie podejście jest preferowane z dwóch powodów.

  1. Zamiar jest wyraźny. Użycie varsłowa kluczowego może łatwo doprowadzić do zadeklarowania jako globalne vars, które miało być lokalne lub odwrotnie. Ten rodzaj określania zakresu zmiennych jest powodem zamieszania dla wielu programistów JavaScript. Dlatego z zasady upewniam się, że wszystkie deklaracje zmiennych są poprzedzone słowem kluczowym varlub prefiksem window.

  2. Standaryzujesz tę składnię do odczytywania zmiennych w ten sposób, co oznacza, że ​​zakres lokalny varnie blokuje globalnego varlub odwrotnie. Na przykład to, co się tutaj dzieje, jest niejednoznaczne:

 

 greeting = "Aloha";

 function foo() {
     greeting = "Hello"; // overrides global!
 }

 function bar(greeting) {
   alert(greeting);
 }

 foo();
 bar("Howdy"); // does it alert "Hello" or "Howdy" ?

Jest to jednak znacznie czystsze i mniej podatne na błędy (tak naprawdę nie musisz pamiętać wszystkich reguł określania zakresu zmiennych):

 function foo() {
     window.greeting = "Hello";
 }

 function bar(greeting) {
   alert(greeting);
 }

 foo();
 bar("Howdy"); // alerts "Howdy"
aleemb
źródło
Dołączanie zmiennych do okna powinno działać we wszystkich przeglądarkach (i jest również moim podejściem, +1!).
Dandy
1
@Dan, jeśli zadeklarujesz "var testvar = 'hello';" poza funkcją, jest automatycznie dodawany do obiektu okna i możesz uzyskać do niego dostęp za pomocą "window.testvar".
zkent
1
@zkent, zgadza się, ale używanie obiektu Window jest nadal lepsze, ponieważ możesz później zamienić swój kod na coś takiego jak kawa.
Nami WANG
Czy lepiej jest używać okna zamiast prefiksu dokumentu?
Andrew,
7

Próbowałeś tego?

Jeśli zrobisz:

var HI = 'Hello World';

W global.js. A następnie wykonaj:

alert(HI);

W js1.jsnim ostrzeże go dobrze. Musisz tylko dołączyć global.jsprzed resztą w dokumencie HTML.

Jedynym haczykiem jest to, że musisz zadeklarować to w zakresie okna (a nie wewnątrz żadnych funkcji).

Możesz po prostu usunąć varczęść i utworzyć ją w ten sposób, ale to nie jest dobra praktyka.

Paolo Bergantino
źródło
7

Jak wspomniano powyżej, występują problemy z używaniem najwyższego zakresu w pliku skryptu. Oto kolejny problem: plik skryptu może być uruchamiany z kontekstu, który nie jest kontekstem globalnym w niektórych środowiskach wykonawczych.

Zaproponowano bezpośrednie przypisanie globalnego do window. Ale jest to również zależne od czasu wykonania i nie działa w Node itp. Pokazuje, że przenośne globalne zarządzanie zmiennymi wymaga dokładnego rozważenia i dodatkowego wysiłku. Może naprawią to w przyszłych wersjach ECMS!

Na razie polecałbym coś takiego, aby wspierać właściwe zarządzanie globalne dla wszystkich środowisk wykonawczych:

/**
 * Exports the given object into the global context.
 */
var exportGlobal = function(name, object) {
    if (typeof(global) !== "undefined")  {
        // Node.js
        global[name] = object;
    }
    else if (typeof(window) !== "undefined") {
        // JS with GUI (usually browser)
        window[name] = object;
    }
    else {
        throw new Error("Unkown run-time environment. Currently only browsers and Node.js are supported.");
    }
};


// export exportGlobal itself
exportGlobal("exportGlobal", exportGlobal);

// create a new global namespace
exportGlobal("someothernamespace", {});

To trochę więcej pisania, ale sprawia, że ​​globalne zarządzanie zmiennymi jest przyszłościowe.

Zastrzeżenie: Część tego pomysłu przyszła mi do głowy podczas przeglądania poprzednich wersji stacktrace.js .

Myślę, że można również użyć Webpacka lub innych narzędzi, aby uzyskać bardziej niezawodne i mniej hakerskie wykrywanie środowiska wykonawczego.

Domi
źródło
2
GLOBALjest obecnie przestarzały i globalpowinien być używany zamiast niego.
Thomas
2

Tak, masz do nich dostęp. Powinieneś zadeklarować je w `` przestrzeni publicznej '' (poza żadnymi funkcjami) jako:

var globalvar1 = 'value';

Możesz uzyskać do nich dostęp później, także w innych plikach.

Ropstah
źródło