Jak myślisz, jakie „ukryte funkcje” JavaScript powinien wiedzieć każdy programista?
Po obejrzeniu doskonałej jakości odpowiedzi na następujące pytania pomyślałem, że nadszedł czas, aby poprosić o JavaScript.
- Ukryte funkcje HTML
- Ukryte funkcje CSS
- Ukryte funkcje PHP
- Ukryte funkcje ASP.NET
- Ukryte funkcje C #
- Ukryte funkcje Java
- Ukryte funkcje Pythona
Mimo że JavaScript jest obecnie prawdopodobnie najważniejszym językiem po stronie klienta (wystarczy zapytać Google), zaskakujące jest to, jak mało twórców stron internetowych docenia jego moc.
javascript
hidden-features
Binoj Antony
źródło
źródło
Odpowiedzi:
Nie musisz definiować żadnych parametrów dla funkcji. Możesz po prostu użyć
arguments
obiektu podobnego do tablicy funkcji .źródło
arguments
obiektu znacznie spowalnia wywoływanie funkcji - np. argumenty if (false); zaszkodzi perf.arguments.callee
jest on przestarzały.Mógłbym zacytować większość doskonałej książki Douglasa Crockforda JavaScript: The Good Parts .
Ale wezmę tylko jeden, zawsze używaj
===
i!==
zamiast==
i!=
==
nie jest przechodni. Jeśli===
go użyjesz , wartość false dla wszystkich tych oświadczeń będzie zgodna z oczekiwaniami.źródło
==
jest'\n\t\r ' == 0
=>true
...: DFunkcje są pierwszorzędnymi obywatelami w JavaScript:
Funkcjonalne techniki programowania można wykorzystać do pisania eleganckiego javascript .
W szczególności funkcje mogą być przekazywane jako parametry, np. Array.filter () akceptuje wywołanie zwrotne:
Możesz także zadeklarować funkcję „prywatną”, która istnieje tylko w zakresie określonej funkcji:
źródło
new Function()
jest tak samo zły jakeval
. Nie używać.Możesz użyć w operatora , aby sprawdzić, czy w obiekcie istnieje klucz:
Jeśli okaże się, że literały obiektów są zbyt brzydkie, możesz połączyć je z bezparametrową wskazówką funkcji:
źródło
Przypisywanie wartości domyślnych do zmiennych
Możesz użyć logicznego lub operatora
||
w wyrażeniu przypisania, aby podać wartość domyślną:a
Zmienna będzie wartośćc
tylko wtedy, gdyb
jest falsy (jeśli jestnull
,false
,undefined
,0
,empty string
, lubNaN
), w przeciwnym raziea
będzie uzyskać wartośćb
.Jest to często przydatne w funkcjach, gdy chcesz nadać argumentowi domyślną wartość, jeśli nie zostanie podany:
Przykład powrotu do IE w procedurach obsługi zdarzeń:
Następujące funkcje językowe są z nami od dawna, wszystkie implementacje JavaScript obsługują je, ale nie były częścią specyfikacji, dopóki ECMAScript 5. edycja :
debugger
oświadczenieOpisane w: § 12.15 Oświadczenie debuggera
Ta instrukcja pozwala programowo wstawiać punkty przerwania w kodzie tylko przez:
Jeśli debugger jest obecny lub aktywny, spowoduje to jego natychmiastowe przerwanie, bezpośrednio na tej linii.
W przeciwnym razie, jeśli debugger nie jest obecny lub aktywny, to instrukcja nie ma zauważalnego wpływu.
Wieloliniowe literały łańcuchowe
Opisane w: § 7.8.4 Literałów ciągowych
Musisz być ostrożny, ponieważ znak obok znaku
\
musi być zakończeniem linii, jeśli\
na przykład po spacji masz kod, kod będzie wyglądał dokładnie tak samo, ale podniesie goSyntaxError
.źródło
JavaScript nie ma zasięgu blokowego (ale ma zamknięcie, więc nazwijmy go nawet?).
źródło
Możesz uzyskać dostęp do właściwości obiektu za pomocą
[]
zamiast.
Pozwala to wyszukać właściwość pasującą do zmiennej.
Można go również użyć do uzyskania / ustawienia właściwości obiektu, których nazwa nie jest prawnym identyfikatorem.
Niektórzy nie wiedzą o tym i używają eval () w ten sposób, co jest naprawdę złym pomysłem :
Jest to trudniejsze do odczytania, trudniejsze do znalezienia błędów (nie można użyć jslinta), wolniejsze do wykonania i może prowadzić do exploitów XSS.
źródło
foo.bar
, zgodnie ze specyfikacją zachowuje się tak samofoo["bar"]
. zauważ również, że wszystko jest właściwością łańcucha. nawet gdy masz dostęp do tablicy,array[4]
4 jest konwertowane na ciąg znaków (ponownie, przynajmniej zgodnie ze specyfikacją ECMAScript v3)Jeśli korzystasz z Googling w poszukiwaniu porządnego odwołania do JavaScript w danym temacie, dołącz słowo kluczowe „mdc” do zapytania, a pierwsze wyniki będą pochodzić z Centrum deweloperów Mozilla. Nie noszę ze sobą żadnych odniesień ani książek offline. Zawsze używam sztuczki „mdc”, aby bezpośrednio dostać się do tego, czego szukam. Na przykład:
Google: javascript array sort mdc
(w większości przypadków możesz pominąć „javascript”)
Aktualizacja: Mozilla Developer Center została przemianowana na Mozilla Developer Network . Sztuczka słów kluczowych „mdc” nadal działa, ale wkrótce będziemy musieli zacząć korzystać z „mdn” .
źródło
Może to trochę oczywiste dla niektórych ...
Zainstaluj Firebug i użyj console.log („cześć”). O wiele lepsze niż używanie random alert ();, które pamiętam wiele lat temu.
źródło
Metody prywatne
Obiekt może mieć metody prywatne.
źródło
Wspomniany również w „Javascript: The Good Parts” Crockforda:
parseInt()
jest niebezpieczny. Jeśli przekażesz ciąg bez informowania go o właściwej podstawie, może zwrócić nieoczekiwane liczby. Na przykładparseInt('010')
zwraca 8, a nie 10. Przekazywanie bazy do analizy składni powoduje, że działa ona poprawnie:źródło
Math.floor
lubNumber
?10 === Math.floor("010"); 10 === Number("010");
unosi się:42 === Math.floor("42.69"); 42.69 === Number("42.69");
parseInt
funkcję można łatwo zrobić, aby zrobić coś nie tak nieszkodliwego.__parseInt = parseInt; parseInt = function (str, base) { if (!base) throw new Error(69, "All your base belong to us"); return __parseInt(str, base); }
Funkcje są obiektami i dlatego mogą mieć właściwości.
źródło
Musiałbym powiedzieć, że funkcje wykonujące się same.
Ponieważ JavaScript nie ma zasięgu blokowego , możesz użyć funkcji samowykonywającej się, jeśli chcesz zdefiniować zmienne lokalne:
W tym przypadku
myvar
nie zakłóca ani nie zanieczyszcza zasięgu globalnego i znika po zakończeniu funkcji.źródło
.js
pliki w anonimową, samoczynnie wykonującą się funkcję i dołączam do obiektu wszystko, co chcę globalnie dostępnewindow
. Zapobiega globalnym zanieczyszczeniom przestrzeni nazw.Dowiedz się, ile parametrów oczekuje funkcja
Dowiedz się, ile parametrów odbiera funkcja
źródło
function.length
.Oto kilka interesujących rzeczy:
NaN
z niczego (nawetNaN
) jest zawsze fałszywe, który zawiera==
,<
i>
.NaN
Oznacza nie liczbę, ale jeśli poprosisz o typ, faktycznie zwraca liczbę.Array.sort
może przyjmować funkcję komparatora i jest wywoływany przez sterownik podobny do szybkiego (zależy od implementacji).$0
,$1
,$2
członkowie na regex.null
jest niepodobne do niczego innego. Nie jest to ani obiekt, wartość logiczna, liczba, ciąg znaków aniundefined
. To trochę jak „alternatywny”undefined
. (Uwaga:typeof null == "object"
)this
zwraca obiekt [Global] którego w przeciwnym razie nie można nazwać.var
, zamiast polegać tylko na automatycznej deklaracji zmiennej, daje środowisku wykonawczemu realną szansę na zoptymalizowanie dostępu do tej zmiennejwith
Konstrukt zniszczy takie optimzationsbreak
. Pętle mogą być oznaczone i używane jako celcontinue
.undefined
. (zależy od implementacji)if (new Boolean(false)) {...}
wykona{...}
blok[zaktualizowano trochę w odpowiedzi na dobre komentarze; zobacz komentarze]
źródło
typeof null
zwraca „obiekt”.undefined
, ale jest to tylko wartość domyślna, którą otrzymasz, gdy szukasz indeksu, który nie istnieje. Jeśli zaznaczyłeś [2000], to też byłobyundefined
, ale to nie znaczy, że jeszcze na to przydzieliłeś pamięć. W IE8 niektóre tablice są gęste, a niektóre rzadkie, w zależności od tego, jak czuł się wówczas silnik JScript. Przeczytaj więcej tutaj: blogs.msdn.com/jscript/archive/2008/04/08/…Wiem, że jestem spóźniony na imprezę, ale nie mogę uwierzyć
+
, że użyteczność operatora nie została wspomniana poza „konwersją czegokolwiek na liczbę”. Może tak dobrze ukryta jest funkcja?Oczywiście możesz to wszystko zrobić za pomocą
Number()
, ale+
operator jest o wiele ładniejszy!Możesz także zdefiniować numeryczną wartość zwracaną dla obiektu, zastępując
valueOf()
metodę prototypu . Żadna konwersja liczb wykonana na tym obiekcie nie spowodujeNaN
, ale zwróci wartośćvalueOf()
metody:źródło
0xFF
itp., Bez potrzeby+"0xFF"
.0xFF
, podobnie jak możesz pisać1
zamiast+true
. Sugeruję, że możesz użyć+("0x"+somevar)
jako alternatywyparseInt(somevar, 16)
, jeśli chcesz.„ Metody rozszerzeń w JavaScript ” za pośrednictwem właściwości prototype.
Spowoduje to dodanie
contains
metody do wszystkichArray
obiektów. Możesz wywołać tę metodę za pomocą tej składniźródło
Aby poprawnie usunąć właściwość z obiektu, powinieneś usunąć właściwość zamiast po prostu ustawić ją na niezdefiniowaną :
Właściwość prop2 nadal będzie częścią iteracji. Jeśli chcesz całkowicie pozbyć się prop2 , powinieneś zamiast tego:
Właściwość prop2 nie będzie się już pojawiać podczas iteracji po właściwościach.
źródło
with
.Jest rzadko używany i, szczerze mówiąc, rzadko przydatny ... Ale w ograniczonych okolicznościach ma swoje zastosowania.
Na przykład: literały obiektów są bardzo przydatne do szybkiego ustawiania właściwości nowego obiektu. Ale co, jeśli musisz zmienić połowę właściwości istniejącego obiektu?
Alan Storm wskazuje, że może to być nieco niebezpieczne: jeśli obiekt użyty jako kontekst nie ma przypisanej jednej z właściwości, zostanie rozwiązany w zewnętrznym zakresie, prawdopodobnie tworząc lub nadpisując zmienną globalną. Jest to szczególnie niebezpieczne, jeśli jesteś przyzwyczajony do pisania kodu do pracy z obiektami, w których właściwości z wartościami domyślnymi lub pustymi pozostają niezdefiniowane:
Dlatego prawdopodobnie dobrym pomysłem jest uniknięcie użycia
with
instrukcji do takiego przypisania.Zobacz także: Czy istnieją uzasadnione zastosowania wyrażenia „with” JavaScript?
źródło
Metody (lub funkcje) można wywoływać na obiektach, które nie są typu, z którym zostały zaprojektowane. Świetnie nadaje się do wywoływania metod rodzimych (szybkich) na obiektach niestandardowych.
Ten kod ulega awarii, ponieważ
listNodes
nie jest toArray
Ten kod działa, ponieważ
listNodes
definiuje wystarczającą liczbę właściwości podobnych do tablicy (operator długości, []) do użycia przezsort()
.źródło
Dziedziczenie prototypowe (spopularyzowane przez Douglasa Crockforda) całkowicie rewolucjonizuje sposób myślenia o mnóstwie rzeczy w JavaScript.
To zabójca! Szkoda, że prawie nikt go nie używa.
Pozwala „spłodzić” nowe wystąpienia dowolnego obiektu, rozszerzyć je, zachowując (żywy) prototypowy link dziedziczący do innych właściwości. Przykład:
źródło
Niektórzy nazwaliby to kwestią gustu, ale:
Operator trójnożny można powiązać, aby działał jak Scheme (cond ...):
można zapisać jako ...
Jest to bardzo „funkcjonalne”, ponieważ rozgałęzia kod bez skutków ubocznych. Więc zamiast:
Możesz pisać:
Działa też dobrze z rekurencją :)
źródło
Liczby są również obiektami. Możesz więc robić fajne rzeczy, takie jak:
źródło
times
nie jest wydajna:Math.floor
jest wywoływana za każdym razem zamiast tylko raz.Co powiesz na zamknięcia w JavaScript (podobne do anonimowych metod w C # v2.0 +). Możesz utworzyć funkcję, która tworzy funkcję lub „wyrażenie”.
Przykład zamknięć :
źródło
Możesz także rozszerzyć (odziedziczyć) klasy i przesłonić właściwości / metody za pomocą prototypowej łyżki łańcuchowej16, o której wspominano.
W poniższym przykładzie tworzymy klasę Pet i definiujemy niektóre właściwości. Zastępujemy również metodę .toString () odziedziczoną z Object.
Następnie tworzymy klasę Dog, która rozszerza Pet i zastępuje metodę .toString () ponownie zmieniając jej zachowanie (polimorfizm). Ponadto dodajemy inne właściwości do klasy potomnej.
Następnie sprawdzamy łańcuch dziedziczenia, aby pokazać, że pies jest nadal typu pies, typu zwierzę i typu obiekt.
Obie odpowiedzi na to pytanie były kodami zmodyfikowanymi ze świetnego artykułu MSDN autorstwa Raya Djajadinaty.
źródło
Możesz wychwycić wyjątki w zależności od ich rodzaju. Cytat z MDC :
UWAGA: warunkowe klauzule catch są rozszerzeniem Netscape (a zatem Mozilla / Firefox), które nie jest częścią specyfikacji ECMAScript i dlatego nie można na nim polegać, z wyjątkiem określonych przeglądarek.
źródło
Z czubka mojej głowy ...
Funkcje
arguments.callee odnosi się do funkcji, która obsługuje zmienną „arguments”, więc można jej użyć do rekurencji funkcji anonimowych:
Jest to przydatne, jeśli chcesz zrobić coś takiego:
Obiekty
Ciekawa rzecz w elementach obiektu: mogą mieć dowolny ciąg znaków jako swoje nazwy:
Smyczki
String.split może przyjmować wyrażenia regularne jako parametry:
String.replace może przyjmować wyrażenie regularne jako parametr wyszukiwania i funkcję jako parametr zastępczy:
źródło
arguments.callee
jest przestarzały i będzie rzucał wyjątek w ECMAScript 5.Przez większość czasu możesz używać obiektów zamiast przełączników.
Aktualizacja: jeśli obawiasz się, że przypadki oceniania z wyprzedzeniem są nieefektywne (dlaczego martwisz się wydajnością już na wczesnym etapie projektowania programu?), Możesz zrobić coś takiego:
Jest to bardziej uciążliwe, aby pisać (lub czytać) niż przełącznik lub obiekt, ale zachowuje zalety korzystania z obiektu zamiast przełącznika, szczegółowo opisane w sekcji komentarzy poniżej. Ten styl ułatwia także przekształcenie go w odpowiednią „klasę”, gdy tylko dorośnie.
update2: staje się to dzięki proponowanym rozszerzeniom składni dla ES.next
źródło
var arr = []; typeof arr; // object
Pamiętaj, aby użyć metody hasOwnProperty podczas iteracji po właściwościach obiektu:
Odbywa się to, aby uzyskać dostęp tylko do bezpośrednich właściwości obiektu anObject , a nie korzystać z właściwości znajdujących się w dół łańcucha prototypów.
źródło
Zmienne prywatne z interfejsem publicznym
Używa schludnej sztuczki z definicją funkcji wywołującej. Wszystko w zwracanym obiekcie jest dostępne w interfejsie publicznym, a wszystko inne jest prywatne.
źródło