Jak utworzyć przestrzeń nazw w JavaScript, aby moje obiekty i funkcje nie były zastępowane innymi obiektami i funkcjami o tej samej nazwie? Użyłem następujących:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
Czy można to zrobić w bardziej elegancki lub zwięzły sposób?
javascript
namespaces
javascript-namespaces
Scott McKenzie
źródło
źródło
Odpowiedzi:
Lubię to:
źródło
MyApp
, np.MyApp.Views.Profile = {}
ZamiastMyApp.users = {}
iMyViews.Profile = {}
. Niekoniecznie, że głębokość powinna wynosić tylko dwa poziomy.Korzystam z podejścia znalezionego na stronie Enterprise jQuery :
Oto ich przykład pokazujący, jak zadeklarować prywatne i publiczne właściwości i funkcje. Wszystko odbywa się jako anonimowa funkcja.
Więc jeśli chcesz uzyskać dostęp do jednego z członków publicznych, po prostu idź
skillet.fry()
lubskillet.ingredients
.Naprawdę fajne jest to, że możesz teraz rozszerzyć przestrzeń nazw przy użyciu dokładnie tej samej składni.
Trzeci
undefined
argumentźródło
undefined
argument jest źródłem zmiennej wartościundefined
. Podczas pracy ze starszymi standardami przeglądarek / javascript (ecmascript 5, javascript <1.8.5 ~ firefox 4) zmienna o zasięgu globalnymundefined
jest zapisywalna, więc każdy może przepisać jej wartość. Dodanie trzeciego, dodatkowego argumentu, którego nie przekazujesz, sprawia, że ma on wartośćundefined
, więc tworzyłeś zakres nazw,undefined
który nie będzie przepisywany przez źródła zewnętrzne.window.skillet = window.skillet || {}
jest to, że pozwala wielu skryptom bezpiecznie dodawać do tej samej przestrzeni nazw, gdy nie wiedzą z góry, w jakiej kolejności będą wykonywane. Może to być pomocne, jeśli chcesz móc dowolnie zmieniać kolejność włączeń skryptu bez zerwania kodu lub jeśli chcesz ładować skrypty asynchronicznie z atrybutem asynchronicznym, a zatem nie masz gwarancji kolejności wykonania. Zobacz stackoverflow.com/questions/6439579/…Innym sposobem na zrobienie tego, co uważam za nieco mniej restrykcyjne niż dosłowna forma obiektu, jest:
Powyższe jest bardzo podobne do wzoru modułu i czy ci się to podoba, czy nie , pozwala ujawnić wszystkie twoje funkcje jako publiczne, unikając sztywnej struktury dosłowności obiektu.
źródło
ns().publicFunction()
, to znaczy ...ns.publicFunction()
działa.new
słowo kluczowe przedfunction
słowem kluczowym. Zasadniczo polega na tym, że deklaruje funkcję anonimową (a jako funkcja jest również konstruktorem), a następnie natychmiast wywołuje ją jako konstruktoranew
. Jako taka, ostateczna wartość, która jest przechowywana w środku,ns
jest (unikalną) instancją tego anonimowego konstruktora. Mam nadzieję, że to ma sens.Tak. Na przykład:
wtedy możesz mieć
źródło
var your_namespace = your_namespace = your_namespace || {}
Zwykle buduję to w zamknięciu:
Mój styl na przestrzeni lat ulegał subtelnej zmianie od momentu napisania tego, a teraz zaczynam pisać w następujący sposób:
W ten sposób łatwiej mi zrozumieć publiczny interfejs API i implementację. Pomyśl o deklaracji return jako o publicznym interfejsie do implementacji.
źródło
MYNS.subns = MYNS.subns || {}
?var foo = function
ifunction foo
będąc podobnymi, będąc prywatnym; ze względu na dynamicznie pisaną naturę JavaScript ten ostatni jest nieco szybszy, ponieważ pomija kilka instrukcji w potokach większości tłumaczy. Zvar foo
, system typów musi zostać wywołany, aby dowiedzieć się, jaki typ jest przypisany do wspomnianego var, natomiast zfunction foo
, system typów automatycznie wie, że jest to funkcja, więc kilka wywołań funkcji jest pomijanych, co przekłada się na mniej wywołań instrukcji procesora, takich jakjmp
,pushq
,popq
, etc, co przekłada się na krótszy rurociągu procesora.function foo
składnia była bardziej czytelna. I nadal lubię moją wersję.Ponieważ możesz pisać różne pliki JavaScript, a następnie łączyć lub nie łączyć ich w aplikacji, każdy musi mieć możliwość odzyskania lub skonstruowania obiektu przestrzeni nazw bez uszkadzania pracy innych plików ...
Jeden plik może używać przestrzeni nazw
namespace.namespace1
:Inny plik może chcieć użyć przestrzeni nazw
namespace.namespace2
:Te dwa pliki mogą żyć razem lub osobno, bez kolizji.
źródło
Oto, jak Stoyan Stefanov robi to w swojej książce Wzory JavaScript, którą uważam za bardzo dobrą (pokazuje również, jak robi komentarze, które pozwalają na automatycznie wygenerowaną dokumentację API i jak dodać metodę do prototypu obiektu niestandardowego):
źródło
Używam tego podejścia:
Kod zewnętrzny może wtedy być:
źródło
ns = ns || {}
może wydawać się bardziej defensywny, może prowadzić do innych nieoczekiwanych rezultatów.Jest to kontynuacja linku user106826 do Namespace.js. Wygląda na to, że projekt został przeniesiony do GitHub . Teraz jest to Smith / namespacedotjs .
Używam tego prostego pomocnika JavaScript do mojego małego projektu i do tej pory wydaje się on być lekki, ale wystarczająco wszechstronny, aby obsługiwać przestrzeń nazw i ładowanie modułów / klas. Byłoby wspaniale, gdyby pozwolił mi zaimportować pakiet do wybranej przeze mnie przestrzeni nazw, nie tylko globalnej przestrzeni nazw ... westchnienie, ale to poza tym.
Pozwala zadeklarować przestrzeń nazw, a następnie zdefiniować obiekty / moduły w tej przestrzeni nazw:
Inną opcją jest jednoczesne zadeklarowanie przestrzeni nazw i jej zawartości:
Więcej przykładów użycia znajduje się w pliku example.js w źródle .
źródło
Próba:
Możesz opcjonalnie zadeklarować
local
zmienną,same
polubićself
i przypisać,local.onTimeout
jeśli chcesz, aby była prywatna.źródło
Możesz zadeklarować prostą funkcję zapewniającą przestrzenie nazw.
źródło
Jeśli potrzebujesz zakresu prywatnego:
w przeciwnym razie, jeśli nigdy nie będziesz używać zakresu prywatnego:
źródło
Wzorzec modułu został pierwotnie zdefiniowany jako sposób zapewnienia enkapsulacji zarówno prywatnej, jak i publicznej dla klas w konwencjonalnej inżynierii oprogramowania.
Podczas pracy ze wzorcem modułu może się przydać zdefiniowanie prostego szablonu, którego używamy do rozpoczęcia pracy z nim. Oto jeden, który obejmuje odstępy między nazwami, zmienne publiczne i prywatne.
W JavaScript wzorzec modułu służy do dalszej emulacji koncepcji klas w taki sposób, że jesteśmy w stanie zawrzeć zarówno metody publiczne / prywatne, jak i zmienne w jednym obiekcie, chroniąc w ten sposób poszczególne części przed zasięgiem globalnym. Powoduje to zmniejszenie prawdopodobieństwa konfliktu nazw naszych funkcji z innymi funkcjami zdefiniowanymi w dodatkowych skryptach na stronie.
Zalety
dlaczego wzorzec modułu jest dobrym wyborem? Na początek jest o wiele czystszy dla programistów pochodzących z obiektowego tła niż idea prawdziwej enkapsulacji, przynajmniej z perspektywy JavaScript.
Po drugie, obsługuje dane prywatne - więc, zgodnie ze wzorem modułu, części publiczne naszego kodu mogą dotykać części prywatnych, jednak świat zewnętrzny nie jest w stanie dotknąć części prywatnych klasy.
Niedogodności
Wady wzorca modułu polegają na tym, że ponieważ w różny sposób uzyskujemy dostęp zarówno do członków publicznych, jak i prywatnych, gdy chcemy zmienić widoczność, musimy wprowadzić zmiany w każdym miejscu, w którym członek był używany.
Nie możemy również uzyskać dostępu do prywatnych członków metodami dodanymi do obiektu w późniejszym czasie . To powiedziawszy, w wielu przypadkach wzorzec modułu jest nadal bardzo przydatny, a przy prawidłowym użyciu z pewnością może poprawić strukturę naszej aplikacji.
Wzorzec modułu ujawniania
Teraz, gdy jesteśmy trochę bardziej zaznajomieni ze wzorem modułu, spójrzmy na nieco ulepszoną wersję - wzór modułu ujawnienia Christiana Heilmanna.
Wzorzec modułu ujawniania pojawił się, gdy Heilmann był sfrustrowany faktem, że musiał powtórzyć nazwę głównego obiektu, gdy chcieliśmy wywołać jedną metodę publiczną z innej lub uzyskać dostęp do zmiennych publicznych. Nie podobało mu się również wymaganie, by wzorzec modułu wymagał zmiany sprzeciwić się dosłownej notacji rzeczy, które chciał upublicznić.
Rezultatem jego wysiłków był zaktualizowany wzorzec, w którym po prostu zdefiniujemy wszystkie nasze funkcje i zmienne w zakresie prywatnym i zwrócimy anonimowy obiekt ze wskazówkami do funkcji prywatnej, którą chcieliśmy ujawnić jako publiczną.
Przykład użycia wzoru modułu ujawniania znajduje się poniżej
Zalety
Ten wzorzec pozwala na bardziej spójną składnię naszych skryptów. Ułatwia także na końcu modułu, do których z naszych funkcji i zmiennych można uzyskać dostęp publiczny, co ułatwia czytelność.
Niedogodności
Wadą tego wzorca jest to, że jeśli funkcja prywatna odnosi się do funkcji publicznej, tej funkcji publicznej nie można zastąpić, jeśli łatka jest konieczna. Wynika to z faktu, że funkcja prywatna będzie nadal odnosić się do prywatnej implementacji, a wzorzec nie dotyczy członków publicznych, a jedynie funkcji.
Członkowie obiektów publicznych, którzy odnoszą się do zmiennych prywatnych, podlegają również powyższym uwagom dotyczącym zasady no-patch.
źródło
Stworzyłem przestrzeń nazw inspirowaną modułami Erlanga. Jest to bardzo funkcjonalne podejście, ale w ten sposób piszę teraz mój kod JavaScript.
Nadaje zamknięciu globalną przestrzeń nazw i udostępnia określone funkcje zestawu w tym zamknięciu.
źródło
Po przeniesieniu kilku moich bibliotek do różnych projektów i konieczności ciągłej zmiany przestrzeni nazw najwyższego poziomu (o nazwie statycznej), przerzuciłem się na tę małą funkcję pomocniczą (open source) do definiowania przestrzeni nazw.
Opis korzyści znajduje się na moim blogu . Możesz pobrać kod źródłowy tutaj .
Jedną z korzyści, które naprawdę lubię, jest izolacja między modułami w odniesieniu do kolejności ładowania. Możesz odwołać się do zewnętrznego modułu PRZED załadowaniem. Otrzymane odwołanie do obiektu zostanie wypełnione, gdy kod będzie dostępny.
źródło
Używam następującej składni dla przestrzeni nazw.
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
źródło
Jestem 7 lat spóźniony na imprezę, ale wykonałem sporo pracy około 8 lat temu:
Ważne jest, aby móc łatwo i wydajnie tworzyć wiele zagnieżdżonych przestrzeni nazw, aby utrzymać złożoną aplikację internetową zorganizowaną i zarządzaną, przy jednoczesnym poszanowaniu globalnej przestrzeni nazw JavaScript (zapobieganie zanieczyszczeniu przestrzeni nazw) i nie blokując jednocześnie żadnych istniejących obiektów na ścieżce przestrzeni nazw .
Z powyższego wynika, że było to moje rozwiązanie około roku 2008:
To nie tworzy przestrzeni nazw, ale zapewnia funkcję tworzenia przestrzeni nazw.
Można to skondensować do zminimalizowanej jednowarstwowej:
Przykład zastosowania:
Lub, jako jedno stwierdzenie:
Albo jest następnie wykonywany jako:
Jeśli nie potrzebujesz obsługi starszych przeglądarek, zaktualizowana wersja:
Byłbym ostrożny z eksponowaniem
namespace
samej globalnej przestrzeni nazw. (Szkoda, że podstawowy język tego nam nie zapewnia!) Zwykle używałbym tego sam w zamknięciu, na przykład:W większej aplikacji należy to zdefiniować tylko raz na początku ładowania strony (w przypadku aplikacji internetowych opartych na kliencie). Dodatkowe pliki mogą następnie ponownie użyć funkcji przestrzeni nazw, jeśli są przechowywane (zawarte powyżej jako „opcjonalne”). W najgorszym przypadku, jeśli funkcja ta zostanie zadeklarowana kilka razy - to tylko kilka wierszy kodu, a mniej, jeśli zostanie zminimalizowana.
źródło
Podoba mi się rozwiązanie Jaco Pretoriusa, ale chciałem uczynić słowo kluczowe „to” nieco bardziej użytecznym, kierując je do obiektu moduł / przestrzeń nazw. Moja wersja patelni:
źródło
Mój ulubiony wzór stał się ostatnio:
Oczywiście zwrot może nastąpić na końcu, ale jeśli podążają za nim tylko deklaracje funkcji, znacznie łatwiej jest zobaczyć, o co chodzi w przestrzeni nazw i jakie API jest widoczne.
Wzorzec używania wyrażeń funkcyjnych w takich przypadkach powoduje, że nie można dowiedzieć się, jakie metody są narażone, bez konieczności przeglądania całego kodu.
źródło
namespace.a();
Myślę, że wszyscy używacie zbyt dużo kodu, aby rozwiązać tak prosty problem. Nie trzeba za to robić repozytorium. Oto funkcja jednej linii.
Spróbuj :
źródło
Jeśli używasz pliku Makefile, możesz to zrobić.
W każdym razie wolę użyć pliku Makefile po przejściu do około 1000 linii, ponieważ mogę skutecznie komentować duże obszary kodu, usuwając jedną linię z pliku makefile. Ułatwia to zabawę. Ponadto dzięki tej technice przestrzeń nazw pojawia się tylko raz w preludium, więc łatwo ją zmienić i nie trzeba powtarzać jej w kodzie biblioteki.
Skrypt powłoki do programowania na żywo w przeglądarce podczas korzystania z makefile:
Dodaj to jako polecenie make „go”, a możesz „make go”, aby aktualizować kompilację podczas pisania kodu.
źródło
Dość kontynuacja odpowiedzi Ionuța G. Stana, ale pokazująca zalety nieuporządkowanego kodu za pomocą
var ClassFirst = this.ClassFirst = function() {...}
, który wykorzystuje zakresy JavaScript zamykania w celu zmniejszenia zaśmiecania przestrzeni nazw dla klas w tej samej przestrzeni nazw.Wynik:
źródło
Napisałem kolejną bibliotekę przestrzeni nazw, która działa trochę bardziej niż pakiety / jednostki w innych językach. Pozwala ci stworzyć pakiet kodu JavaScript i odniesienie do tego pakietu z innego kodu:
Plik hello.js
Plik Przykład.js
Na stronie musi znajdować się tylko drugi plik. Jego zależności (plik hello.js w tym przykładzie) zostaną automatycznie załadowane, a obiekty wyeksportowane z tych zależności zostaną wykorzystane do wypełnienia argumentów funkcji wywołania zwrotnego.
Powiązany projekt można znaleźć w pakiecie JS .
źródło
Możemy używać go niezależnie w ten sposób:
źródło
Moim nawykiem jest używanie funkcji myName () jako pamięci właściwości, a następnie var myName jako posiadacza „metody” ...
Niezależnie od tego, czy jest to wystarczająco uzasadnione, czy nie, pobij mnie! Cały czas polegam na mojej logice PHP i wszystko po prostu działa. :RE
if (this !== that) myObj.fName1(); else myObj.fName2();
Odniesienie do tego: JavaScript: Tworzenie obiektu za pomocą Object.create ()
źródło
W JavaScript nie ma predefiniowanych metod korzystania z przestrzeni nazw. W JavaScript musimy stworzyć własne metody definiowania przestrzeni nazw. Oto procedura, którą stosujemy w technologiach Oodles.
Zarejestruj przestrzeń nazw Poniżej znajduje się funkcja rejestracji przestrzeni nazw
Aby zarejestrować Przestrzeń nazw, wystarczy wywołać powyższą funkcję z argumentem jako przestrzeń nazw oddzieloną
'.'
(kropką). Na przykład Niech twoja nazwa aplikacji to oodles. Możesz utworzyć przestrzeń nazw, wykonując następującą metodęZasadniczo utworzy strukturę NameSpaces, jak poniżej w backend:
W powyższej funkcji masz zarejestrowaną przestrzeń nazw o nazwie
"oodles.HomeUtilities"
i"oodles.GlobalUtilities"
. Aby wywołać te przestrzenie nazw, tworzymy zmienną, tj. Var$OHU
i var$OGU
.Te zmienne są niczym innym jak aliasem do inicjalizacji przestrzeni nazw. Teraz, ilekroć zadeklarujesz funkcję, która należy do
HomeUtilities
ciebie, zadeklarujesz ją następująco:Powyżej znajduje się inicjalizacja nazwy funkcji i jest umieszczana w przestrzeni nazw
$OHU
. i do wywołania tej funkcji w dowolnym miejscu w plikach skryptów. Wystarczy użyć następującego kodu.Podobnie z innymi nazwami.
Mam nadzieję, że to pomoże.
źródło
JavaScript domyślnie nie obsługuje przestrzeni nazw. Jeśli więc utworzysz dowolny element (funkcję, metodę, obiekt, zmienną), staje się on globalny i zanieczyszcza globalną przestrzeń nazw. Weźmy przykład definiowania dwóch funkcji bez przestrzeni nazw,
Zawsze wywołuje definicję drugiej funkcji. W takim przypadku przestrzeń nazw rozwiąże problem kolizji nazw.
źródło