Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Obiekt JSON vs singleton
Forum PHP.pl > Forum > Po stronie przeglądarki > JavaScript
pp-layouts
Zrobiłem sobie klasę AJAX, będącą zestawem narzędzi i mającą jakieśtam swoje właściwości (do konfiguracji). Utworzyłem ją jako zwykły obiekt, będący zmienną globalną mniej więcej tak:

Kod
var AJAX = {
  property1 : null,
  property2 : null,
  method1 : function() {
    ...
  }
}



Odwołuję się do niej prosto: AJAX.method1(); . Komodo Edit daje prawidłowe podpowiedzi do właściwości i metod.
Co więcej, w środku utworzyłem więcej modułów JSON, tak że mogę odwoływać się do nich per AJAX.module1.method1().

Wszystko pięknie. Prawie dokładny odpowiednik klasy statycznej w PHP. Nawet lepiej, bo to klasa która może zawierać inne klasy. Moduł składający się z modułów. Git.

W takim razie po co używać singletonów? Co one mogą, czego nie może moduł JSON?

Zrobiłem pełną edycję poprzedniego posta, bo nikt chyba nie złapał o co mi w ogóle chodzi.

230005
Przecież to co zrobiłeś, to jest właśnie js-owy singleton więc nie rozumiem skąd pytanie... Hmmm, a co to według ciebie jest moduł JSON?
yevaud
moze chodzi o roznice miedzy zmienianiem prototypu, a budowaniem obiektu spod palca - jak tutaj
pp-layouts
Chodzi mi o to, że czytałem kiedyś artykuł o użyciu singletonów w JS (z resztą, w PHP jest ten sam problem). Prawidłowy (kanoniczny) singleton jest obiektem, który jest instancją klasy, a różni się od nie-singletona tylko tym, że jest jedyną dopuszczalną instancją, co może zostać wymuszone jego własnym kodem.

Bardzo nie podoba mi się ta idea, bo wydaje mi się sztuką dla sztuki - tzn programistyczne wymuszanie na klasie, żeby dopuszczała tylko jedną instancję. Jeśli nie potrzebuję więcej niż 1 instancji - to ich nie tworzę! Nie mogę zakładać, że mojej klasy będzie używał idiota do nie wiadomo czego. Programowanie polega chyba na pisaniu rzeczy do konkretnych celów, znaczy się... deterministic smile.gif

Wracając jednak do tych moich JSON-ów jak je nazwałem, a dokładniej i ściślej są to chyba object literale - to nie jest sztuka dla sztuki, tylko piękne i łopatologiczne uproszczenie całej masy rzeczy. Weźmy tak - mam liba, który zajmuje się interfejsem AJAX-owym. Wyświetla kręciołki, okienka, statusy, uaktualnia rzeczy itede... Mój interfejs aplikacji ma kilka stałych punktów, żeby user nie musiał za każdym razem szukać wzrokiem czy myszką, po prostu pewne rzeczy są na swoich miejscach. Logiczne jest, że odwołuję się do tego przez wspólny obiekt, wspólnego liba, ściślej - jest to grupa funkcji wewnątrz pewnej przestrzeni nazw, zdefiniowanych jako object literal.

Ma to sens, podobnie jak np Math. Nie muszę tworzyć instancji Math żeby używać Math.PI. Dalszy sens jest taki, że maksymalnie skraca wywołanie. Z dowolnego miejsca kodu piszę costam.fn(). Najszybciej, najkrócej. W php costam::fn(). Mało tego, piszę costam, a NetBeans czy KomodoEdit od razu pokazuje mi ładną listę wszystkiego co może costam. Owszem, jest to programowanie strukturalne, ale vide Math w JS - w OOP używa się tego też i basta, chyba właśnie po to jest wzorzec singletona, czy może się mylę?

I teraz samo sedno mojego pytania: o co chodzi w tych całych singletonach, gdzie autorzy tutoriali pokazują, jak za wszelką cenę nie wolno stworzyć "klasy statycznej", tylko dynamiczny obiekt, następnie utworzyć jego instancję, a potem dopilnować, żeby mogła utworzyć się tylko jedna! PO JAKIEGO GRZYBA, JA SIĘ PYTAM BO SERIO NIE ROZUMIEM!

Programuję od kilku lat, mam dziesiątki jak nie setki tysięcy linii kodu w PHP i JavaScript za sobą, a tego jak nigdy nie rozumiałem, tak nie rozumiem.

W PHP oczywistym jest dla mnie:

Kod
class krowa {
  public static function mu() {
  }
}



i odwołanie się do tego via:


Kod
krowa::mu();



niż jakieś udziwnienia typu (pominę już tworzenie klasy, wrzucę tylko wywołanie):

Kod
krowa::getInstance()->mu();



Chodzi o stan obiektu? Jeśli obiekt jest singletonem, jaka jest różnica pomiędzy stanem w zmiennych statycznych, a zmiennych jedynej instancji? Chodzi o to, że wewnętrzna implementacja w C kompilatora jakoś inaczej to wykonuje?

Przez jakiś czas myślałem, że coś jest ze mną nie tak, dopóki nie przeczytałem kilku ciekawych artów o JS, gdzie object literale były przedstawione jako zupełnie normana i nawet polecana technika. Widziałem je też w samym jQuery i kilku niezłych wtyczkach do niego.

Po cóż więc singletony z nieszczęsnym getInstance? smile.gif Czyżby kaprys programistów przyzwyczajonych do języków, w których nie da się zdefiniować klasy statycznej lub object literala?

zegarek84
Cytat(pp-layouts @ 10.01.2010, 09:27:26 ) *
I teraz samo sedno mojego pytania: o co chodzi w tych całych singletonach, gdzie autorzy tutoriali pokazują, jak za wszelką cenę nie wolno stworzyć "klasy statycznej", tylko dynamiczny obiekt, następnie utworzyć jego instancję, a potem dopilnować, żeby mogła utworzyć się tylko jedna! PO JAKIEGO GRZYBA, JA SIĘ PYTAM BO SERIO NIE ROZUMIEM!

pogrubiłem i podkreśliłem - w zasadzie nie zauważyłeś, ale sam sobie odpowiedziałeś na pytanie - tworząc dynamicznie obiekt dynamicznie a nie od razu przydzielasz mu dynamicznie miejsce w pamięci, gdzie niby pierwsze wywołanie będzie odrobinę wolniejsze gdyż tego obiektu nie ma jeszcze w pamięci (w zasadzie nie zauważalna różnica), jednak jeśli np. bibliotekę masz b.dużą i masz jeszcze szereg być może potrzebnych i podobnych do siebie klas - zwracających to samo jednak muszą być inne bo to będzie zależało od sytuacji - ta sama struktura, te same metody - aczkolwiek nie wgłębiając się choć metody mają te same dane wyjściowe to inaczej np. działają bo jedną klasą parsujesz np. csv a druga w konstruktorze przyjmuje plik xml (wiem - to już nie js - ale tak na szybko przykład) - w jakimś "sterowniku" decydujesz którą klasę użyć i przydzielasz jej w pamięci dynamicznie miejsce... podczas gdy klasy całe w sobie są statyczne to one już jakieś tam miejsce w tej pamięci zajmują...

trochu tu odbiegam od singleton, ale nie zawsze też tej klasy np. się używa... i zazwyczaj moim zdaniem to po prostu zbiór metod (a raczej funkcji pogrupowanych tematycznie) gdzie potrzebna jest tylko jedna instancja - jest jakby bezpostaciowa ta klasa więc po co ma zajmować więcej pamięci przez kolejne jej obiekty?? - po za tym raczej go tworzą tak, żeby był też dostęp w wewnętrznych funkcjach/klasach - na co pozwalają statyczne metody, statyczny obiekt - ale po co on od razu ma istnieć w całości?? - skąd wiesz, że zawsze go użyjesz w każdej sytuacji??

ps. może inny temat ale ja JSON używam do pogrupowania tematycznie zmiennych, po za tym w samym JSON nie zrobisz w js zmiennych prywatnych i metod prywatnych - ale jest bardzo wygodny do zwracania metod publicznych oraz zmiennych publicznych - w js nie lubię pisać co chwila this.cośtam - wolę tu json'a który jest naturalnym językiem dla js...

po za tym pisząc w json też możesz nadać instancje klasie...

jakiś czas temu zadałem na forum tutaj pytanie i różnicy chyba nie ma - ja jej nie widzę i nikt mi nie odpowiedział:
[JavaScript] Obiekty
pp-layouts
Proszę, wytłumacz dokładniej, w jaki sposób klasa statyczna zajmuje więcej miejsca w pamięci. Czy kod metod niestatycznych nie zużywa miejsca w pamięci jeśli nie są użyte? Czyli jak, dopiero zaczynają używać miejsce po pierwszym użyciu?

A propos Twojego pierwszego posta, to pewnie wina przykładu, zbyt abstrakcyjny, może gdybyś zapodał na czymś bardziej konkretnym. Nie rozumiem też, co ma w ogóle JSON (a właściwie object literal, bo JSON wymaga, żeby nazwy właściwości pisać z użyciem cudzysłowów) do "this". This-a można używać odnosząc się do wnętrza literala (namespace-a), a można do instancji klasy, zależnie od kontekstu. To czy zapiszę klasę w formie funkcji, czy zapiszę ją jako obiekt OL - cóż, wydaje mi się, że to tylko kwestia zapisu, nie ma to chyba żadnych innych implikacji, bo próbowałem na dużych klasach tych 2 sposobów zapisu zamiennie i wydawały się działać dokładnie identycznie. Przy zapisie w OL może wystąpić niejednoznaczność "this". Ale tylko w przypadku kiedy nie przypisuje się bezpośrednio obiektu do prototypu. Wtedy w kontekście OL będzie oznaczać namespace, a w kontekście instancji tą instancję.

Co do metod i zmiennych prywatnych - to znów wydaje mi się sztuką dla sztuki, bo z tego co wiem, JavaScript tego po prostu nie obsługuje, ale można to wymusić - kosztem skomplikowania kodu. I znów z tego co wiem, dostępność zmiennych i metod ogranicza się dla ułatwienia życia, stąd umyka mi sens tej operacji. (Poza może very very defensive programming). Bo jeśli chodzi o ułatwienie życia developerom, to o wiele prostszy i wygodniejszy jest JSDoc, gdzie można opisać sobie klasy i dostępność keywordami takimi jak @class, @public, @private, @final itede.

Jak znajdę trochę czasu wolnego, muszę zrobić kiedyś trochę benchmarków różnych rozwiązań - zobaczymy w praktyce co jest szybsze i o ile.

Jak już mówimy o szybkości, zastanawia mnie też, czemu wszędzie używa się if (typeof(zmienna) == 'undefined') zamiast if (zmienna === undefined). Pierwsze wydaje mi się dużo wolniejsze, bo wymaga porównania napisów, a drugie odpala super szybką funkcję systemową, zbliżoną strukturalnie do isNan(). Wiem, że można złośliwie przypisać do undefined jakąś wartość, ale znów pojawia się pytanie - po co?

Dalej, jQuery używa lokalnych definicji undefined, które są === undefined. Czytałem, że to przyspiesza kod, ale czy na tyle znacząco, żeby używać tego poza frameworkiem? I czy aby jest to jeszcze aktualne dla nowych silników JS? (FF3.5, O10, Chrome 3)

zegarek84
Cytat(pp-layouts @ 10.01.2010, 17:12:24 ) *
Jak już mówimy o szybkości, zastanawia mnie też, czemu wszędzie używa się if (typeof(zmienna) == 'undefined') zamiast if (zmienna === undefined). Pierwsze wydaje mi się dużo wolniejsze, bo wymaga porównania napisów, a drugie odpala super szybką funkcję systemową, zbliżoną strukturalnie do isNan(). Wiem, że można złośliwie przypisać do undefined jakąś wartość, ale znów pojawia się pytanie - po co?

to nie chodzi o przypisanie wartości - jak w temacie do którego podałem link zauważyłeś to jestem bardziej hobbistą ale... na szybko sprawdziłem i stwierdzam - musiałbyś mieś pewność, że ta zmienna została jakoś zdefiniowana przynajmniej, czy jakoś zainicjowana gdzieś - i nie mam na myśli wartości - szybko to sprawdziłem w pasku adresu wpisując:
java script:if(a === undefined)alert('fffffff');void(0); //to nie działa
a to zadziała:
java script:var a; if(a === undefined)alert('ffff');void(0); //to działa
podczas gdy typeof zadziała także dla nie zainicjowanych zmiennych - jeśli odpowiednio jest kod napisany można zrezygnować z typeof, już przy samej definicji funkcji function cos(a,cool.gif{...} jakby inicjujemy te zmienne (choćby nie przypisując wartości)

Cytat(pp-layouts @ 10.01.2010, 17:12:24 ) *
Dalej, jQuery używa lokalnych definicji undefined, które są === undefined. Czytałem, że to przyspiesza kod, ale czy na tyle znacząco, żeby używać tego poza frameworkiem? I czy aby jest to jeszcze aktualne dla nowych silników JS? (FF3.5, O10, Chrome 3)

zanim w prost wyjaśnię napiszę co innego - js jest bardzo mocno obiektowy, mocniej niż nie jednemu się wdaje (dawniej sam tego nie wiedziałem), a to, że jest inny (i niby łatwy, bo do prostych rzeczy jest łatwy), oraz to, że inaczej definiuje się obiekty niż "normalnie" wielu wprowadza w błąd...
i dalej to pasowało by na to o co pytasz spojrzeć patrząc na zasięg zmiennych w js - w php od tak do zewnętrznych zmiennych nie ma zasięgu...

i teraz czy w js warto "buforować" odwołanie do obiektu bądź zmiennąquestionmark.gif samo undefined o którym piszesz jest w obiekcie window - szukając zmiennych funkcja w pierw sprawdza czy jest ona zdefiniowana lokalnie - nie ma jej to idzie w górę (sam wiesz, że obiekty można zagnieżdżać - funkcje w js też - i teraz tak przechodzi przez wszystkie obiekty aż do ostatniego gdzie jest zdefiniowana zmienna w ostatnim obiekcie window (obiekcie globalnym - no może nie do końca - nie chcę tutaj polemizować ;p).... alo znowu zboczyłem z tematu - a czy słusznie - może i tak...

jeśli tylko raz coś sprawdzasz, do czegoś wewnątrz tylko raz się odwołujesz to nie warto, lecz jeśli wewnątrz masz pętlę i tych porównań jest wiele to warto, lub jeśli danej metody często używasz to możesz tą zmienną zbuforować bliżej jej zasięgu.... - to jest tak jak z odwołaniami do elementu DOM - przecież w pętli nie będziesz co chwila szukał elementu przez document.getElementsByTagName('bleble')[0] - skoro zawsze używasz tego samego obiektu bądź jego wartości, podobnie count w php powinno się obliczyć na początku, żeby nie liczyło co każde sprawdzenie warunku...


ale główny temat był o singleton ;p
Cytat(pp-layouts @ 10.01.2010, 17:12:24 ) *
Proszę, wytłumacz dokładniej, w jaki sposób klasa statyczna zajmuje więcej miejsca w pamięci. Czy kod metod niestatycznych nie zużywa miejsca w pamięci jeśli nie są użyte? Czyli jak, dopiero zaczynają używać miejsce po pierwszym użyciu?


z tego co mi wiadomo pamięć jest przydzielona od razu by dana metoda, funkcja mogły zostać użyte w każdym momencie a nie dopiero po pierwszym użyciu, metody statyczne i zmienne są wszędzie także w zasięgu - ja bym to przyrównał (ale w duuużym skrócie i ogólnikowo - czyli to nie jest to samo!!!) raczej trochu do stosu i sterty znanego z c++, przy czym pierwsze jest niby szybsze, ale z tym z kolei nie można przesadzać...

poza tym na te pytania jakie zadajesz w js zaciekawi Cię kilka filmików (no nie wszystkie ale kilka jest tam ciekawych):
http://developer.yahoo.com/yui/theater/
pp-layouts
Hm, filmów jeszcze nie przejrzałem, bo aktualnie (wiem, że jest niedziela, ale mam deadline z projektem na jutro) pracuję smile.gif Co do singletonów - z tego co piszesz, to ja już nieśmiało wnioskuję, że to chyba żadna, albo prawie żadna różnica, czy sobie zdefiniuję jakąś funkcjonalność w klasie statycznej, czy w kanonicznym singletonie z getInstance, tak czy siak kompilator musi cały kod sparsować, a kwestię inicjowania naszych toolkitów na razie pomijamy (też da się to tak samo ekonomicznie zrobić w jednym i drugim przypadku, moje statyczne klasy mają metodę init() tam gdzie jest potrzebna, oczywiście w pierwszej linii tej metody jest sprawdzenie jednej ze zmiennych statycznych, żeby odpuścić sobie wykonywanie więcej niż raz).

Co do undefined - dzięki, faktycznie, odwołanie do niezadeklarowanej zmiennej operatorem === powoduje wysypanie JS, debugger zwraca błąd i przerywa wykonywanie skryptu. Użycie typeof jest za to nieszkodliwe. Cóż, metoda porównania bezpośredniego będzie szybsza do sprawdzania czy podano parametr funkcji czy nie. Co do szukania zmiennych - tak, teraz rozumiem o co tu chodzi, to bardzo logiczne, stąd nabiera sensu początek jQuery 1.3.2:


[JAVASCRIPT] pobierz, plaintext
  1. (function() {
  2. var
  3.   // Will speed up references to window, and allows munging its name.
  4.   window = this,
  5.   // Will speed up references to undefined, and allows munging its name.
  6.   undefined,
[JAVASCRIPT] pobierz, plaintext



Pokombinuję jeszcze z tym jak będę optymalizował swój projekt, na razie ma "tylko" działać smile.gif

Z optymalizacji, których używam standardowo, to większość selektorów jQuery odpalam tylko raz po uruchomieniu kodu, a potem odwołuję się do wyników. Dodatkowo używam funkcji find, która w zasadzie robi to samo co context, tylko "z ręki". Różnica w szybkości działania jest zauważalna gołym okiem. I gdzie się da - odwołania po id. Odwołania do zmiennych opłaca się optymalizować tylko w pętlach, albo w event handlerach, gdzie event jest stosunkowo często odpalany. jQuery siłą rzeczy jest najczęściej mielonym kodem, więc ma największy wpływ na wydajność.

To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.