Czy fakt, że anonimowe zamknięcia funkcji odwołujących się do siebie są tak popularne w JavaScript, sugeruje, że JavaScript jest niekompletną specyfikacją? Widzimy tak wiele z tego:
(function () { /* do cool stuff */ })();
i przypuszczam, że wszystko jest kwestią gustu, ale czy to nie wygląda jak kludge, kiedy wszystko, czego chcesz, to prywatna przestrzeń nazw? Czy JavaScript nie może zaimplementować pakietów i odpowiednich klas?
Porównaj z ActionScript 3, również opartym na ECMAScript, gdzie masz
package com.tomauger {
import bar;
class Foo {
public function Foo(){
// etc...
}
public function show(){
// show stuff
}
public function hide(){
// hide stuff
}
// etc...
}
}
W przeciwieństwie do zwojów, które wykonujemy w JavaScript (to z dokumentacji autorskiej wtyczki jQuery ):
(function( $ ){
var methods = {
init : function( options ) { // THIS },
show : function( ) { // IS },
hide : function( ) { // GOOD },
update : function( content ) { // !!! }
};
$.fn.tooltip = function( method ) {
// Method calling logic
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
};
})( jQuery );
Rozumiem, że to pytanie z łatwością może przerodzić się w rant na temat preferencji i stylów programowania, ale tak naprawdę jestem bardzo ciekawy, jak przyprawiliście się o tym doświadczeni programiści i czy wydaje się to naturalne, jak uczenie się różnych osobliwości nowego języka lub kludgy , jak obejście niektórych podstawowych składników języka programowania, które po prostu nie zostały zaimplementowane?
źródło
Odpowiedzi:
Większość komentarzy jest sprzecznych z mitem, że „prototypy są klasami biednych ludzi”, więc powtórzę, że OO oparte na prototypach nie jest gorsze od OO opartego na klasach.
Drugi punkt to „kludge, gdy wszystko, czego chcesz, to prywatna przestrzeń nazw”. Możesz być zaskoczony, wiedząc, że Schemat używa dokładnie tej samej kludge do definiowania zakresów. To nie powstrzymało od stania się archetypowym przykładem dobrze wykonanego zakresu leksykalnego.
Oczywiście w schemacie „kludge” jest ukryty za makrami ...
źródło
Po pierwsze, kilka rzeczy:
Innym sposobem patrzenia na JavaScript jest 1 milion i 1 rzeczy, które możesz zrobić z funkcją jako konstrukcją. Wszystko tam jest, jeśli jej szukasz. Po prostu nigdy nie jest daleko od funkcji.
Ta kwestia tworzenia wtyczek jQuery jest okropna. Nie mam pojęcia, dlaczego oni to popierają. Rozszerzenia $ powinny być rzeczami ogólnego użytku, które $ już ma całkiem dobrze pokryte, a nie metodami budowania mnie jako kompletnego widgetu. To narzędzie normalizacyjne DOM-API. Jego użycie najlepiej jest zakopać wewnątrz własnych obiektów. Nie widzę potrzeby używania go jako pełnego repozytorium biblioteki interfejsu użytkownika.
Pakiety w sieci po stronie klienta są bezcelowe
To, czego osobiście nie lubię w pakietach po stronie klienta, to to, że udajemy, że robimy coś, czym tak naprawdę nie jesteśmy. W post-webformach internetowych i gobach przerażających rzeczy, których nigdy nie wymanewrowałeś z naszych przyjaciół Java, wolałbym myśleć o kawałku HTML z połączonymi zasobami jako tym, czym naprawdę jest i nie próbujcie uspokoić programistów aplikacji odpornych na naukę nowych systemów operacyjnych, udając, że to coś innego. W JS w sieci po stronie klienta nic nie zostaje „zaimportowane”, z wyjątkiem robienia czegoś okropnego z Ajaxem, który działa w nieświadomości buforowania przeglądarki, co tak wielu próbowało zrobić. Dla przeglądarki liczy się tylko to, że została ona załadowana i zinterpretowana lub nie. Nie mamy więcej kodu ukrytego na kliencie dostępnym do użycia „na wszelki wypadek” z dobrych powodów. # 1 to, że właśnie opisałem zależności wtyczek i przeglądarek dla aplikacji internetowych, ponieważ zjawisko to na ogół nie działało zbyt dobrze. Chcemy teraz sieci. Nie po tym, jak Adobe lub Sun dokonają aktualizacji po raz trzeci w tym tygodniu.
Język ma to, czego potrzebuje do struktury
Obiekty JS są wysoce zmienne. Możemy mieć rozgałęzione drzewa przestrzeni nazw w każdym stopniu, w którym uznamy to za przydatne i jest to bardzo łatwe. Ale tak, w przypadku wszystkiego, co można ponownie wykorzystać, musisz przykleić katalog główny dowolnej biblioteki do globalnej przestrzeni. W każdym razie wszystkie zależności są powiązane i ładowane jednocześnie, więc po co robić cokolwiek innego? Celem unikania globalnej przestrzeni nazw nie jest to, że wszystko jest złe. Jest zbyt wiele rzeczy, które są złe, ponieważ ryzykujesz kolizją przestrzeni nazw lub przypadkowym zastąpieniem podstawowych funkcji języka.
To, że jest popularny, nie oznacza, że robimy to dobrze
Teraz, gdy zobaczysz to w aplikacji internetowej po stronie klienta:
Problemem nie jest to, że brakuje nam narzędzi do strukturyzacji aplikacji, problem polega na tym, że ludzie nie cenią struktury. W przypadku 2-3 stron jednorazowych tymczasowych stron internetowych z agencji projektowej naprawdę nie mam z tym problemu. Kiedy robi się brzydko, musisz zbudować coś łatwego w utrzymaniu, czytelnym i łatwym do modyfikacji.
Ale kiedy dotrzesz do miejsca, w którym nadszedł czas, aby po prostu zaimplementować wszystkie przedmioty wielokrotnego użytku i fabryki, a może jeden lub dwa nowe tymczasowe pojazdy mogą wkraść się w ten proces, to wygoda.
Ale są implementacje JS z pakietami / modułami
Należy pamiętać, że w Node.js, gdzie takie rzeczy mają o wiele większy sens, mają moduły. JS, zakładając, że możemy uniknąć uber-config-hell, który plagi innych języków, jest jedyną rzeczą w równaniu, a każdy wykonywany plik ma swój własny izolowany zakres. Ale na stronie internetowej samo połączenie pliku js jest instrukcją importu. Wykonanie większego importu w locie to tylko strata czasu i zasobów, ponieważ uzyskanie zasobów wymaga dużo więcej wysiłku niż zwykłe dodawanie linków do plików, ponieważ potrzebujesz ich, wiedząc, że zostaną one zapisane w pamięci podręcznej w przeglądarce, jeśli kolejna strona będzie ich ponownie potrzebować. Próbuje więc podzielić przestrzeń globalną, robiąc cokolwiek innego niż tworzenie fabryk obiektów adapterów, takich jak jQuery lub bardziej tradycyjne obiekty, które obejmują duży podzbiór zadań w danej domenie, zajmując jedno miejsce w globalnym. Tam'http://wiki.ecmascript.org/doku.php?id=harmony:modules
Więc nie, nie ma nic złego w automatycznych wywoływaczach używanych do unikania globalnego zanieczyszczenia przestrzeni nazw, gdy istnieje dobry powód, aby używać takich rzeczy (częściej niż nie ma). I mamy trwałe właściwości ekwiwalentu prywatnego w naszych obiektach (wystarczy zdefiniować zmienną w konstruktorze i nie ujawniać jej jako właściwości).
Jednak fakt, że MOŻEMY robić takie rzeczy, jest niesamowity. Częste użycie jest oznaką, że programiści JS wciąż mogą dojrzewać, ale nie jest to luka w języku dla każdego, kto nie próbuje narzucić paradygmatu na stronę po stronie klienta, co po prostu nie ma sensu.
źródło
Inną rzeczą, której brakuje, jest to, że javscript musi być kompatybilny wstecz. Jeśli spróbujesz wprowadzić składnię pakietu, może to naprawdę popsuć sieć w szalony sposób. To by było złe! Doug Crockford mówił o tym w różnych punktach i dlaczego próby dodania go nie powiodły się.
źródło
Tak, to kludge.
Wiele osób mówi, że „prototypy nie są gorsze od klas”. Nie zgadzam się, ale to kwestia preferencji. Ale to nawet nie jest prawdziwy problem z JavaScript - problem polega na tym, że został pierwotnie zaprojektowany jako szybki i brudny język skryptowy do tworzenia animowanych przycisków. W połowie lat 90. nikt nigdy nie myślał, że JavaScript zostanie poproszony o zrobienie szalonych rzeczy, które robi teraz.
źródło
Anonimowe funkcje wywołujące są bardziej podobne do modułów niż klas. To denerwujące, że domyślnym skryptem javascript jest uruchamianie w zakresie globalnym. Komitet pracujący nad JS.next poważnie rozważa dodanie modułów, aby nie upuścić zmiennych lokalnych w zasięgu globalnym. Na szczęście funkcje Javascript mają tak dogodną semantykę, że możemy stosunkowo łatwo używać funkcji anonimowej jako zakresu prywatnego.
Nie rozumiem, w jaki sposób klasy naprawdę w ogóle biorą udział w dyskusji, z wyjątkiem tego, że są konstrukcją określającą zakres najwyższego poziomu w wielu językach. Lepiej byłoby mieć lepszą konstrukcję moduł / pakiet / proszę-daj-mi-lokalny-zasięg-tak-i-nie-zostawiaj-moje-zmienne-w-globalnym środowisku.
źródło
Możesz rzucić okiem na ExtJS 3 i 4, gdzie udało im się całkiem dobrze zaimplementować przestrzenie nazw.
- dodane po -1
Chodzi mi o to, że można ukryć wszystkie te „zwoje” i nadal mieć całkiem przyjazny kod:
źródło