Szukam ostatecznej odpowiedzi na pytanie, dlaczego rozszerzanie wbudowanych prototypów jest tak surowo karane w społeczności programistów JS. Od jakiegoś czasu korzystam z frameworka JS Prototype i [1,2,3].each(doStuff)
wydaje mi się, że jest o wiele bardziej elegancki niż $.each([1,2,3], doStuff)
. Wiem, że powoduje to „zanieczyszczenie przestrzeni nazw”, ale nie rozumiem, dlaczego uważa się to za coś złego. Czy istnieje też jakikolwiek rzeczywisty spadek wydajności związany z rozszerzaniem wbudowanych prototypów? Dzięki!
15
for(var ... in ...)
pętle są pomieszane, ponieważ przekazywane są również funkcje prototypowe.Odpowiedzi:
Proponuję ci przeczytać tego artykułu, który moim zdaniem wyjaśnia całkiem dobrze, dlaczego rozszerzanie obiektów jest złym pomysłem, również w odniesieniu do Prototypu.
W podsumowaniu:
Brak specyfikacji
Obiekty hosta nie mają reguł
Szansa na kolizje
Koszty ogólne wydajności
IE DOM to bałagan
Bonus: błędy przeglądarki
źródło
Innym powodem jest czytelność / konserwacja kodu. Jeśli inny programista (szczególnie początkujący) czyta mój kod i widzi
[0, 1, 2].foo(...)
, może nie wiedzieć, co to jest metoda foo lub gdzie znaleźć dokumentację / źródło dla niej. Czy foo jest rozszerzeniem języka dodanego przez prototype.js, inną używaną bibliotekę lub inną część mojego kodu w innym pliku, czy jest to natywna metoda JavaScript, o której nie wiedzieli? Muszą na nie polować i mogą go nie znaleźć od razu (lub jeśli występują konflikty, mogą nie znaleźć właściwego).Jeśli widzisz podejście jQuery,
$.foo(...)
przestrzeń nazw metody foo wyraźnie pokazuje, gdzie można znaleźć jej definicję / dokumentację, jeśli nie wiesz, co ona robi.źródło
Oto podstawowy problem: co się stanie, jeśli masz dwa narzędzia, które rozszerzają prototypy w niekompatybilny sposób, lub które rozszerzają powszechnie nazywane metody w taki sposób, że dają różne wyniki (jest to szczególny problem
for...in
w JavaScript), powodując w ten sposób kod zależny na ich normalnym zachowaniu do zerwania?Zasadniczo są to te same problemy, które występują przy niewłaściwym użyciu zmiennych globalnych. Samo w sobie może nie dzieje się nic złego. Ale to otwiera cię na kłopoty, gdy nagle dwa pozornie oddzielne fragmenty kodu natrafiają na siebie (a debugowanie, kiedy to się dzieje, jest trudne).
Z pewnością prototype.js jest dość dobrze znany i większość narzędzi działa w oparciu o to, co robi. Podobnie, jestem pewien, że istnieją przypadki, w których rozszerzenie prototypów podstawowych jest właściwym rozwiązaniem. Ale do tego należy podchodzić ostrożnie.
źródło
Nie jestem pewien, czy to nadal jest problem, ale moje doświadczenia z wcześniejszymi wersjami programu Internet Explorer są takie, że czasami nie było nawet możliwe rozszerzenie niektórych wbudowanych typów.
źródło
Istnieją tutaj dwa osobne problemy. Pierwszym z nich jest ogólne rozszerzenie wbudowanych prototypów, a drugim - rozszerzenie prototypów DOM. Argumenty przeciwko rozszerzaniu wbudowanych prototypów:
Array.prototype
lubObject.prototype
może mieć efekt domina, taki jak dodanie metod rozszerzenia wyliczanych wfor...in
pętliJeśli chodzi o rozszerzanie prototypów DOM, powyższy argument potencjalnego zderzenia nadal obowiązuje. Ponadto węzły DOM są obiektami hosta i jako takie nie podlegają żadnej z normalnych zasad rodzimych obiektów JavaScript. Mogą zasadniczo robić to, co lubią i nie są zobowiązani do dostarczania sensownych obiektów prototypowych, a nawet dopuszczania dodatkowych właściwości („expando”). IE w szczególności skorzysta z tego prawa, zapewniając żadnych prototypów DOM dla obiektów przed IE 9 i posiadające różne weirdnesses o właściwościach na różnych obiektach DOM (chociaż jesteś ogólnie OK właściwości przypisanie elementów, przewidzianych zestaw Nic
document.expando
sięfalse
).źródło