Zastosowanie modułów JavaScript
z Mozilla Developer Center, polskiego centrum programistów Mozilli.
Ten artykuł obejmuje funkcje wprowadzone w Firefoksie 3
Moduły JavaScript zostały wprowadzone w Firefoksie 3 (Gecko 1.9) i służą do udostępniania kodu pomiędzy różnymi zakresami kodu uprzywilejowanego. Za pomocą modułów można także utworzyć globalne obiekty typu singleton, co dotychczas wymagało korzystania z obiektów JavaScript XPCOM. Moduł JavaScript to po prostu kod w języku JavaScript, umieszczony w zarejestrowanej lokalizacji. Moduł jest ładowany w ramach określonego zakresu JavaScript, takiego jak skrypt XUL lub skrypt JavaScript XPCOM, za pomocą metody Components.utils.import.
Poniżej przedstawiono przykład prostego modułu JavaScript:
EXPORTED_SYMBOLS = ["foo", "bar"]
function foo() {
return "foo";
}
var bar = {
name : "bar",
size : "3"
};
var dummy = "dummy";
Do tworzenia funkcji, obiektów, stałych oraz dowolnych innych typów obiektów JavaScript stosowana jest zwykła składnia języka JavaScript. W module zdefiniowany jest także specjalny obiekt typu Array o nazwie EXPORTED_SYMBOLS. Każdy element kodu JavaScript umieszczony w tablicy EXPORTED_SYMBOLS zostanie wyeksportowany z modułu i dołączony do zakresu, do którego importowany jest moduł — na przykład:
Components.utils.import("resource://aplikacja/moduly/moj_modul.jsm");
alert(foo()); // wyświetla "foo"
alert(bar.size + 3); // wyświetla "6"
alert(dummy); // wyświetla "dummy is not defined", ponieważ zmienna 'dummy' nie została wyeksportowana z modułu
Szczególnie istotną cechą działania metody Components.utils.import jest umieszczanie ładowanych modułów w pamięci podręcznej; przy kolejnych operacjach importu zamiast ładowania nowej wersji modułu używana jest wersja pobrana z pamięci podręcznej. W przypadku wielokrotnego importowania danego modułu jest on współużytkowany. Jakiekolwiek modyfikacje danych, obiektów lub funkcji są dostępne w każdym zakresie, do którego moduł został zaimportowany. Jeżeli na przykład do dwóch różnych zakresów JavaScript zostanie zaimportowany prosty moduł, zmiany dokonane w jednym zakresie będą widoczne w pozostałych zakresach.
Zakres 1:
Components.utils.import("resource://app/modules/moj_modul.jsm");
alert(bar.size + 3); // wyświetla "6"
bar.size = 10;
Zakres 2:
Components.utils.import("resource://app/modules/moj_modul.jsm");
alert(foo()); // wyświetla "foo"
alert(bar.size + 3); // wyświetla "13"
Możliwe jest tworzenie obiektów typu singleton, które mogą udostępniać dane do innych okien, skryptów XUL i komponentów XPCOM.
[edytuj] Protokół resource:
W przykładach zastosowania metody Components.utils.import użyto protokołu "resource://". Podstawową składnię adresu URL protokołu resource przedstawiono poniżej:
resource://<alias>/<ścieżka-względna>/<plik.js|jsm>
<alias> jest aliasem lokalizacji; zazwyczaj jest to fizyczna lokalizacją względna wobec aplikacji lub środowiska uruchomieniowego XUL. W środowisku uruchomieniowym XUL istnieją dwa wstępnie zdefiniowane aliasy:
-
app— alias lokalizacji aplikacji XUL. -
gre— alias lokalizacji środowiska uruchomieniowego XUL.
<ścieżka-względna> może zawierać wiele zagłębień i jest zawsze względna wobec lokalizacji określonej przez <alias>. Typowa ścieżka względna to "modules" — taka nazwa jest używana w środowisku XUL Runner i w programie Firefox. Moduły kodu to pliki JavaScript z rozszerzeniem .js lub .jsm.
Najprostszym sposobem dodania własnych aliasów w rozszerzeniach i aplikacjach XUL jest zarejestrowanie tych aliasów w manifeście chrome za pomocą poniższego kodu:
resource nazwa_aliasu adres/url/plików/
Własne aliasy można także w sposób programowy dodać do protokołu resource, na przykład:
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var resProt = ioService.getProtocolHandler("resource")
.QueryInterface(Components.interfaces.nsIResProtocolHandler);
var aliasFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
aliasFile.initWithPath("/bezwzględna/ścieżka");
var aliasURI = ioService.newFileURI(aliasFile);
resProt.setSubstitution("mojalias", aliasURI);
// przyjęto założenie, że moduły kodu znajdują się w folderze określonym przez alias, a nie w podfolderach
Components.utils.import("resource://mojalias/plik.jsm");
// ...