ugrás a tartalomhoz

Maintainable JavaScript: Don’t modify objects you don’t own

Török Gábor · 2010. Már. 23. (K), 13.43
Ne változtassuk meg azon objektumok viselkedését, amiket nem mi írtunk
 
1

Nem meggyőző példa

vbence · 2010. Már. 23. (K), 14.47
A példában a Prototype alatti kód:
document.getElementsByClassName("myclass").each(doSomething);
Az ebből születő problémának szerintem nincs köze a document módosításához. A probléma az, hogy a Prototype API-ját időközben önkényesen (azaz lefele nem kompatibilisen) módosították, és eltűnt a fenti funkcionalitás.

A natív implementáció nyilván gyorsabb, mint a (példa idején használt) JS. Ez viszont nem ok arra, hogy egy egyszerű wrapper továbbra is ott legyen, ami továbbra is Array-t ad vissza és biztosítja a kompatibilitást.

A verziók közi inkompatibilitás egyértelmű védjegye a rossz minőségű szoftvernek, és itt csupán erről van szó.
2

A cikkben másról van szó…

Adam · 2010. Már. 24. (Sze), 23.00
…lehet érdemes lesz újra elolvasni az ide vonatkozó részt, ugyanis arról van szó, hogy a Prototype getElementsByClassName() metódusa egy Array-t, míg a natív metódus NodeList-et ad vissza, és amíg a Prototype — ha natívan nem volt, — az Array-t kibővítette az each()-csel, addig a NodeList-et nem, így ahol a böngészőben implementálva lett a getElementsByClassName(), ott a fenti kód nem futott le.

És akkor ebből következik az, hogy a beépített objektumok prototype-jának módosítésa idővel, mi után látják a specifikációk kidolgozói, hogy mit igényelnek az emberek, natívan beépítik a specifikációba, emiatt a bővített működések a saját megoldásokban nem fognak működni, mivel a JavaScript-ben az objektumok saját metódusait nem tudod override-olni — és nem is sok értelme lenne.

Az utolsó mondatoddal pedig szintén nem tudok egyetérteni — ha jól értelmezem azt, de lehet nem, ez majd kiderül a válaszodból: a PHP nyelvnek kifejezetten jót tenne, ha a most fejlesztés alatt álló 6-os verzió nem lenne visszafele kompatibilis az 5-ös verzióval és kijavítanák a nyelv szintaktikai betegségeit. Hiszen miért korlátozzon be egy — akár évtizedekkel korábban — "hibásan" elgondolt API a későbbi fejlesztések során, pláne ha egyértelmű major és nem minor verzió váltás történik?
6

Egyáltalán nem értem, hogy

vbence · 2010. Már. 25. (Cs), 14.25
Egyáltalán nem értem, hogy Document vagy az Array működésének megváltoztatása itt a rossz ötlet.

Nem programoztam prototype-ra, úgyhogy a következők lehet, hogy hibásak. Amennyire látom a módszer az, hogy egy prototype-féle metódussal kapsz vissza egy elemet (mondjuk a $ függvénnyel), ami fel lesz díszítve a megfelelő funkcionalitással (így nem lesz gond tetszőleges DOM elemek kezelése, nem csak a document-é).

Ennek nincs akadálya:

document.__originalGetElementsByClassName = document.getElementsByClassName;
getElementsByClassName = function (s) {
    var nodeList = document.__originalGetElementsByClassName(s);
    var array = new Array();
    // nodeList átopörgetése array-ba
    return array;
}
...és máris a megszokott (elvárt) API-t kapjuk.

JavaScript-ben az objektumok saját metódusait nem tudod override-olni

Ezt nem tudom hogy érted.

Az utolsó mondatoddal pedig szintén nem tudok egyetérteni

Ez megérne egy új topicot. Témaindítónak: JAVA :)
10

Remélem válasz lesz

Adam · 2010. Ápr. 5. (H), 11.57
Ennek nincs akadálya

Persze, csak akkor nem az elemnek (mert ugyebár ezeket a metódusokat bármely HTML elemen használhatod), hanem csak a window-nak tudod meghívni ezt a tulajdonságát, így nem az elvárt API-t kapjuk, csak abban az esetben, ha eredetileg is window.getElementsByClassName()-et akartunk hívni.

JavaScript-ben az objektumok saját metódusait nem tudod override-olni

Ezt nem tudom hogy érted.

Vegyük alapul az alert() metódust, ami ugye a window objektumnak egy saját metódusa. Ilyet nem tehetsz meg JavaScriptben:

window.alert = function(text)
{
    // Lightbox szerű implementáció
    […]
}
Ez megérne egy új topicot. Témaindítónak: JAVA :)

Sajnos nem tartom magam annyira hozzáértőnek, hogy ennek kapcsán kielégítő topicnyitó üzenetet írjak… Te igen? Mert hozzászólnom valószínű könnyebb lenne :)

És írjunk web-es petíciót, hogy a PHP7 az már ne legyen visszafele kompatibilis!
11

?????

Ustak · 2010. Ápr. 5. (H), 19.57
Vegyük alapul az alert() metódust, ami ugye a window objektumnak egy saját metódusa. Ilyet nem tehetsz meg JavaScriptben:
window.alert = function(text)  
{  
    // Lightbox szerű implementáció  
    […]  
}

Akkor légyszíves illeszd be ezt a kódot a firebug javascript konzoljába is futtasd le.

window.alert("no");
window.alert = function(){
    console.log("no");
}
window.alert();
"java == javascript mint car == carpet" :-)
Üdv:
Gábor
3

feature sniffing?

Ustak · 2010. Már. 24. (Sze), 23.41
Én azon csodálkozom, hogy a Prototype-ban nincs ilyen, hogy "megnézem előbb vajh natívan implementálva van -e az adott metódus", azaz:

if (!document.getElementsByClassName()) {
    //balba
Vagy olyan büdös az a feature, hogy már meg se lehet szagulni? :-)
4

Helyesen if

tgr · 2010. Már. 25. (Cs), 12.45
Helyesen

if (!document.getElementsByClassName) {  
de ettől még a natív és a Prototype változatnak más a visszatérési értéke, vagyis a javascript library megváltoztatja a natív DOM API-t, ami nyilvánvalóan nem egy jó ötlet.
5

Igen, köszi,

Ustak · 2010. Már. 25. (Cs), 14.24
kikapcsoltam a gépet akkor jutott eszembe.
7

DOM API

vbence · 2010. Már. 25. (Cs), 14.29
Aki keretrendszert használ, aza keretrendszer API-ját használja, nem hiszem, hogy kérdés bárkinek, hogy a natív vagy az importált API kell elsőbbséget élvezzen.

Sokan [who] azért használnak keretrendszert, mert a DOM-on keresztüli manipulálást túl fapadosnak/időtrablónak tartják. Nekik nem hiszem, hogy nagy törést okoz, hogy egy DOM feature-t nem használhatnak ki, ha a választott API-juk erre már bejáratott megoldást kínál.
8

Nagy törést okoz, mert

tgr · 2010. Már. 25. (Cs), 17.44
Nagy törést okoz, mert bármilyen 3rd party script, ami arra számít, hogy egy működő DOM API-t talál, elromolhat. (A NodeList máshogy viselkedik, mint egy sima tömb, pl. ha megváltoztatod egy elem osztályát, az valós időben eltűnik belőle.) Ezt a jQuery csinálja szépen, eleve nem a létezővel egy névtérbe kell tenni az új APIt.
9

Jogos

vbence · 2010. Már. 25. (Cs), 19.30
Teljesen egyet értek, remek érvelés. Jó lett volna ha a cikkben is ezt használják :)