Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Dodawanie metod do ciała obiektu``
wukkie
post
Post #1





Grupa: Zarejestrowani
Postów: 9
Pomógł: 2
Dołączył: 30.05.2012

Ostrzeżenie: (0%)
-----


Witajcie,

Przy pisaniu skryptu JS natrafiłem na pewien problem związany z rozszerzaniem głównego obiektu Array. Gdy dodam metody w taki sposób

  1.  
  2. Array.prototype.x =function(){return this;}
  3. Array.prototype.z=function(){return this;}
  4.  
  5. x = [1,2,3]
  6.  
  7. for ( var i in x ){
  8. console.log( x[i] );
  9. }
  10. console.log(x.length)
  11.  


Okaże się że tablica x ma aż 3 elementy, natomiast pętla zwróci zarówno 3 elementy jak i te dwie nowe metody. Czy znacie składnie która pozwoliła by dodawać metody do ciała obiektu, możliwe do wywołania, ale nie widoczne w pętli jako kolejne elementy?

Ten post edytował wukkie 10.06.2012, 17:51:02
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 8)
AdIoS_Neo
post
Post #2





Grupa: Zarejestrowani
Postów: 159
Pomógł: 43
Dołączył: 8.03.2009

Ostrzeżenie: (0%)
-----


Witam,
do tablicy w JavaScripcie (a właściwie do danych w niej) uzyskujemy dostęp poprzez indek, np.:
[JAVASCRIPT] pobierz, plaintext
  1. var a = [1, "dwa"];
  2. a[0]; // daje -> 1
  3. a[1] // daje -> dwa
[JAVASCRIPT] pobierz, plaintext
W JS tablica jest również obiektem więc jeśli użyjesz pętli for(var i in a){} to uzyskujesz dostęp nie tylko do danych ale także do pól i metod tego obiektu, tak więc nie da się osiągnąć efektu o który pytasz. Jeśli chcesz wypisać wszystkie elementy z tablicy to musisz użyć pętli w takiej postaci:
[JAVASCRIPT] pobierz, plaintext
  1. var a = [1, "dwa"];
  2. for(var i=0;i<a.length;i++) a[i];
[JAVASCRIPT] pobierz, plaintext


Pozdrawiam
Go to the top of the page
+Quote Post
konrados
post
Post #3





Grupa: Zarejestrowani
Postów: 623
Pomógł: 79
Dołączył: 16.01.2008

Ostrzeżenie: (0%)
-----


Możesz sprawdzać czy typeof x[i]!='function'

Tu masz o typeof: http://www.adp-gmbh.ch/web/js/operators/typeof.html
Go to the top of the page
+Quote Post
wukkie
post
Post #4





Grupa: Zarejestrowani
Postów: 9
Pomógł: 2
Dołączył: 30.05.2012

Ostrzeżenie: (0%)
-----


Jest to oczywiście rozwiązanie, ale zasięg takiej zmiany jest zbyt nieprzewidywalny. Wykorzystanie dowolnego modułu w którym pojawiły by się operacje na elementach tablic były by awaryjne.


Cytat(AdIoS_Neo @ 10.06.2012, 18:59:12 ) *
Witam,
do tablicy w JavaScripcie (a właściwie do danych w niej) uzyskujemy dostęp poprzez indek, np.:
[JAVASCRIPT] pobierz, plaintext
  1. var a = [1, "dwa"];
  2. a[0]; // daje -> 1
  3. a[1] // daje -> dwa
[JAVASCRIPT] pobierz, plaintext
W JS tablica jest również obiektem więc jeśli użyjesz pętli for(var i in a){} to uzyskujesz dostęp nie tylko do danych ale także do pól i metod tego obiektu, tak więc nie da się osiągnąć efektu o który pytasz. Jeśli chcesz wypisać wszystkie elementy z tablicy to musisz użyć pętli w takiej postaci:
[JAVASCRIPT] pobierz, plaintext
  1. var a = [1, "dwa"];
  2. for(var i=0;i<a.length;i++) a[i];
[JAVASCRIPT] pobierz, plaintext


Pozdrawiam

Zgadza się,
natomiast problem pojawia sie w przypadku gdy posiadam tablicę asocjacyjną.
Tj.
  1. x = []
  2. x["a"] = 1


W tym przypadku nie mogę wykorzystać pętli for ( i=0... ).
Owszem dostaję dostęp do metod, ale tylko dodanych przeze mnie. Co ciekawe w przypadku gdy posiadam tylko jedną dodaną funkcję
w postacie
  1. Array.prototype.x = function(){this}

problem nie występuje.

Ten post edytował wukkie 10.06.2012, 18:47:10
Go to the top of the page
+Quote Post
AdIoS_Neo
post
Post #5





Grupa: Zarejestrowani
Postów: 159
Pomógł: 43
Dołączył: 8.03.2009

Ostrzeżenie: (0%)
-----


właśnie ... jest przecież metoda hasOwnProperty(nazwa) która sprawdza czy obiekt ma takie pole lub metodę i zwraca true lub false. jeśli dopisujesz metody do głównego obiektu to wystarczy sprawdzić w pętli czy jest to pole/metoda tego obiektu np.:
[JAVASCRIPT] pobierz, plaintext
  1. for ( var i in x ){
  2. if(x.hasOwnProperty(i))
  3. console.log( x[i] );
  4. }
[JAVASCRIPT] pobierz, plaintext

oczywiście sprawdzenie metody "x" lub "z" które nie są bezpośrednimi metodami obiektu x da wynik false i nie zostaną one wyświetlone. Problem będzie jeśli napiszemy tak:
[JAVASCRIPT] pobierz, plaintext
  1. x.x = function(){ return "tralala";}
[JAVASCRIPT] pobierz, plaintext
wtedy metoda x staje się bezpośrednią metodą obiektu x i sprawdzenie x.hasOwnProperty("x") da wynik true.

Ten post edytował AdIoS_Neo 10.06.2012, 19:34:35
Go to the top of the page
+Quote Post
wukkie
post
Post #6





Grupa: Zarejestrowani
Postów: 9
Pomógł: 2
Dołączył: 30.05.2012

Ostrzeżenie: (0%)
-----


Tak, to rozwiązanie jest podobne do tego z typeof i wymusza dodawanie tego warunku w każdej pętli która znajduje się w skrypcie. Lecz co w przyadku gdy wykorzystuje kod napisany przez innego użytkownika i nie przewidział takiego zachowania podczas wywoływania pętli for..in ?

Być może takie rozwiązanie nie istnieje, lecz jestem ciekaw, ze względu na to że problem występuje dopiero przy dwóch dodadnych metodach. Prędzej zrezygnuje z rozszerzeania głównych obiektów niż sprawie że każda pętla for..in będzie wymagała modyfikacji. smile.gif

Może macie doświadczenia z takim problemem?
Go to the top of the page
+Quote Post
AdIoS_Neo
post
Post #7





Grupa: Zarejestrowani
Postów: 159
Pomógł: 43
Dołączył: 8.03.2009

Ostrzeżenie: (0%)
-----


Inaczej tego nie obejdziesz niestety, tak w ogóle w JavaScript nie ma tablic asocjacyjnych jak wcześniej napisałeś, a pętla powinna Ci wypisać także jedną metodę którą dodałeś, jeśli tego nie robi to jest gdzieś błąd.
Go to the top of the page
+Quote Post
kamil4u
post
Post #8





Grupa: Zarejestrowani
Postów: 2 350
Pomógł: 512
Dołączył: 4.01.2009
Skąd: Wrocław / Świdnica

Ostrzeżenie: (0%)
-----


Bo w praktyce rzadko się używa prototype do obiektów globalnych( Array, HTMLElement, itd. ) - przynajmniej ja tak robię smile.gif

Używałbym w takim przypadku metody a'la jQuery, czyli tworzenie własnego obiektu i manipulowanie dopiero nim.
Czyli w przykładzie jQuery mamy $(...).operacja(); , a nie operacje bezpośrednio na elementach DOM( HTMLElement.prototype.operacja = .... ).

Kod
var tablica = ....;
mojObiektObslugującyTablice( tablica ).x();
mojObiektObslugującyTablice( tablica ).y();


--------------------
Go to the top of the page
+Quote Post
wukkie
post
Post #9





Grupa: Zarejestrowani
Postów: 9
Pomógł: 2
Dołączył: 30.05.2012

Ostrzeżenie: (0%)
-----


Cytat(AdIoS_Neo @ 10.06.2012, 20:53:58 ) *
Inaczej tego nie obejdziesz niestety, tak w ogóle w JavaScript nie ma tablic asocjacyjnych jak wcześniej napisałeś, a pętla powinna Ci wypisać także jedną metodę którą dodałeś, jeśli tego nie robi to jest gdzieś błąd.

Faktycznie jest jakaś niespójność i nie wiem skąd się bierze.


Przypadek a: localhost - jedna metoda dodana
  1. Array.prototype["f"] = function(){}
  2. var x = [1,2]
  3. for (var i in x) console.log(x[i]);


Rezultat firebug:
0 1
1 2

1,2

Przypadek b: localhost - dwie metody
  1. Array.prototype["f"] = function(){}
  2. Array.prototype["g"] = function(){}
  3. var x = [1,2]
  4. for (var i in x) console.log(x[i]);

Rezultat firebug:

0 1
1 2
test function()

__proto__ []
constructor [undefined]
prototype []

1,2,function()

Przypadek c:
http://jsbin.com/acozus/edit#javascript,html,live
i tu już wszystko jest jak powinno, czyli odrazu metody sie pojawiają jako elementy w pętli.

Na chromie jest podobnie na moim localhoscie. Jakieś pomysły? worriedsmiley.gif

Cytat(kamil4u @ 10.06.2012, 22:50:56 ) *
Bo w praktyce rzadko się używa prototype do obiektów globalnych( Array, HTMLElement, itd. ) - przynajmniej ja tak robię smile.gif

Używałbym w takim przypadku metody a'la jQuery, czyli tworzenie własnego obiektu i manipulowanie dopiero nim.
Czyli w przykładzie jQuery mamy $(...).operacja(); , a nie operacje bezpośrednio na elementach DOM( HTMLElement.prototype.operacja = .... ).

Kod
var tablica = ....;
mojObiektObslugującyTablice( tablica ).x();
mojObiektObslugującyTablice( tablica ).y();


Zgadza się wszystko, jednak naturalnym miejscem dla metod do manipulacji na samej tablicy, dobrze by był to ten obiekt - biorąc pod uwagę że posiada "wiedzę" potrzebną do wykonania takiego zobowiązania. Po prostu było by to gromadzenie jednego rodzaju operacji w jednej "klasie".

Ten post edytował wukkie 10.06.2012, 23:16:40
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 22.08.2025 - 04:24