Typ zmiennej sprawdzającej JavaScript. Dynamiczna identyfikacja typu
Operator typ zwraca ciąg znaków wskazujący typ operandu.
Składnia
Operand jest zgodny z operatorem typeof:
Typ operand
Opcje
operand jest wyrażeniem reprezentującym obiekt lub element pierwotny, którego typ ma zostać zwrócony.
Opis
Poniższa tabela przedstawia możliwe wartości zwracane przez typeof. Dodatkowe informacje o typach i prymitywach jest na stronie.
Przykłady
// Typ liczb 37 === "liczba"; typeof 3.14 === "liczba"; typeof(42) === "liczba"; typ Math.LN2 === "liczba"; typ Infinity === "liczba"; typ NaN === "liczba"; // pomimo tego, że jest to typ Number(1) === "number"; // nigdy nie używaj tego wpisu! // Typ ciągów "" === "string"; typeof "bla" === "string"; typeof "1" === "string"; // zauważ, że liczba wewnątrz ciągu jest nadal typu string typeof (typeof 1) === "string"; // w tym przypadku typeof zawsze zwróci ciąg znaków typeof String("abc") === "string"; // nigdy nie używaj tego wpisu! // Wartość logiczna true === "boolean"; typeof false === "boolean"; typeof Boolean(true) === "boolean"; // nigdy nie używaj tego wpisu! // Symbole typeof Symbol() === "symbol" typeof Symbol("foo") === "symbol" typeof Symbol.iterator === "symbol" // Niezdefiniowany typ niezdefiniowany === "niezdefiniowany"; typeofdeklarowanyButUndefiniVariable === "niezdefiniowany"; typeof undeclaredVariable === "niezdefiniowany"; // Typ obiektów (a: 1) === "obiekt"; // użyj Array.isArray lub Object.prototype.toString.call // aby rozróżnić zwykłe obiekty od tablic typeof === "object"; typeof new Date() === "obiekt"; // To, co następuje, prowadzi do błędów i problemów. Nie używaj! typeof new Boolean(true) === "obiekt"; typeof new Number(1) === "obiekt"; typeof new String("abc") === "obiekt"; // Funkcje typeof funkcja() () === "funkcja"; typ klasy C() === "funkcja"; typeof Math.sin === "funkcja";zero
// Zostało to zdefiniowane od urodzenia JavaScript typeof null === "obiekt";Na początku Implementacje JavaScriptu wartości były reprezentowane przez parę typu tagu i wartości. Typ znacznika dla obiektów to 0. wartość null była reprezentowana jako wskaźnik zerowy (0x00 na większości platform). Dlatego typ tagu dla null miał wartość null, więc wartość zwracana przez typeof jest fikcyjna. ()
Zaproponowano poprawkę w ECMAScript (poprzez wyłączenie), ale została ona odrzucona. Spowodowałoby to typeof null === "null" .
Korzystanie z nowego operatora
// Wszystkie funkcje konstruktora utworzone za pomocą „new” będą typu „object” var str = new String("String"); var num = nowa liczba (100); typ str; // Zwraca typ obiektu num; // Zwraca „obiekt” // Istnieje jednak wyjątek dla konstruktora funkcji var func = new Function(); rodzaj funkcji; // Zwróć „funkcję”Wyrażenia regularne
Możliwość wywołania wyrażenia regularne były niestandardowym dodatkiem w niektórych przeglądarkach.
Typ /s/ === "funkcja"; // Chrome 1-12 Nie jest zgodny z ECMAScript 5.1 typeof /s/ === "obiekt"; // Firefox 5+ Zgodny z ECMAScript 5.1
Błędy związane z tymczasowymi martwymi strefami
Przed ECMAScript 2015 było to gwarantowane typ operatora zwróci ciąg znaków dla dowolnego operandu, z którym zostało wywołane. Zmieniło się to po dodaniu deklaracji let i const o zasięgu blokowym. Teraz, jeśli zmienne są zadeklarowane za pomocą let i const, a typeof zostanie wywołany na nich w bloku deklaracji zmiennej, ale przed deklaracją, zostanie zgłoszony błąd ReferenceError. Zachowanie różni się od niezadeklarowanych zmiennych, dla których typeof zwróci „niezdefiniowane”. Zmienne o zasięgu blokowym mają „tymczasową martwą strefę”, która trwa od początku bloku do momentu zadeklarowania zmiennej. W tej strefie próba dostępu do zmiennych zgłasza wyjątek.
Typ niezadeklarowanej zmiennej === "niezdefiniowany"; typ nowej zmiennej Let; niech newLetVariable; // Typ błędu referencyjnego newConstVariable; const nowaConstVariable = "cześć"; //Błąd odniesienia
Wyjątki
We wszystkim aktualne przeglądarki Istnieje niestandardowy obiekt hosta document.all, który jest typu Niezdefiniowany.
Typ dokumentu.all === "nieokreślony";
Chociaż specyfikacja dopuszcza niestandardowe nazwy typów dla niestandardowych obiektów egzotycznych, wymaga, aby nazwy te różniły się od predefiniowanych. Za wyjątkowe naruszenie regulaminu należy uznać sytuację, gdy document.all jest typu undefinied.
Dane techniczne
Specyfikacja | Status | Uwagi |
---|---|---|
Najnowsza wersja robocza ECMAScript (ECMA-262) |
Projekt | |
ECMAScript 2015 (wydanie 6, ECMA-262) Definicja „typu operatora” znajduje się w tej specyfikacji. |
Standard | |
ECMAScript 5.1 (ECMA-262) Definicja „typu operatora” znajduje się w tej specyfikacji. |
Standard | |
ECMAScript, wydanie 3. (ECMA-262) Definicja „typu operatora” znajduje się w tej specyfikacji. |
Standard | |
ECMAScript, wydanie pierwsze (ECMA-262) Definicja „typu operatora” znajduje się w tej specyfikacji. |
Standard | Wstępna definicja. Zaimplementowano w JavaScript 1.1 |
Zgodność przeglądarki
Zaktualizuj dane dotyczące zgodności w GitHub
Komputery | mobilny | serwer | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Chrom | Krawędź | Firefoksa | Internet Explorera | Opera | Safari | Przeglądarka internetowa na Androida | Chrome na Androida | Firefoksa na Androida | Opera na Androida | Safari na iOS | Internetu Samsunga | Node.js | |
typ | Chrom Pełne wsparcie 1 | Krawędź Pełne wsparcie 12 | Firefoksa Pełne wsparcie 1 | TJ. Pełne wsparcie 3 | Opera Pełne wsparcie Tak | Safari Pełne wsparcie Tak | Przeglądarka internetowa na Androida Pełne wsparcie 1 | Chrome na Androida Pełne wsparcie 18 | Firefoksa na Androida Pełne wsparcie 4 | Operę na Androida Pełne wsparcie Tak | Safari na iOS Pełne wsparcie Tak | Internetowy Samsung z Androidem Pełne wsparcie 1.0 | nodejs Pełne wsparcie Tak |
Legenda
Pełne wsparcie Pełne wsparcieUwagi specyficzne dla IE
W IE 6, 7 i 8 wiele obiektów hostów to obiekty, ale nie funkcje. Na przykład.
Dynamiczna identyfikacja typu
Dynamiczna identyfikacja typu (RTTI) pozwala określić typ obiektu podczas wykonywania programu. Okazuje się, że jest to przydatne z wielu powodów. W szczególności, korzystając z odniesienia do klasy bazowej, można dość dokładnie określić typ obiektu dostępnego poprzez to odwołanie. Dynamiczna identyfikacja typu pozwala również sprawdzić z wyprzedzeniem, jak skuteczne będzie rzutowanie typu, zapobiegając wyjątkowi z powodu nieprawidłowego rzutowania typu. Ponadto dynamiczna identyfikacja typu jest głównym składnikiem odbicia.
Aby obsługiwać dynamiczną identyfikację typów, C# udostępnia trzy słowa kluczowe a: is, as i typeof. Każde z tych słów kluczowych zostało kolejno omówione poniżej.
jest operatorem
Konkretny typ obiektu można określić za pomocą operatora is. Poniżej znajduje się jego ogólna postać:
wyrażenie to typ
gdzie wyrażenie oznacza pojedyncze wyrażenie opisujące obiekt, którego typ jest testowany. Jeśli wyrażenie jest typu zgodnego lub tego samego co testowany typ, wówczas wynikiem tej operacji jest prawda, in W przeciwnym razie- FAŁSZ. Zatem wynik będzie prawdziwy, jeśli wyrażenie ma typ testowany w tej czy innej formie. Operator is definiuje oba typy jako kompatybilne, jeśli są tego samego typu lub jeśli zapewniona jest konwersja odwołań, pakowanie lub rozpakowywanie.
Poniżej znajduje się przykład użycia operatora is:
Korzystanie z systemu; przestrzeń nazw ConsoleApplication1 ( klasa Add ( ) class Sum: Add ( ) class Program ( static void Main() ( Add a = new Add(); Sum s = new Sum(); if (a to Add) Console.WriteLine("Variable a jest typu Add"); if (s jest Sum) Console.WriteLine("Typ zmiennej s jest dziedziczony z klasy Add"); Console.ReadLine(); ) ) )
Operator jako
Czasami chcesz przeprowadzić konwersję typu w czasie wykonywania, ale nie zgłaszaj wyjątku, jeśli konwersja się nie powiedzie, co jest całkiem możliwe w przypadku rzutowania typów. Służy do tego operator as, który ma następującą ogólną postać:
wyrażenie jako typ
gdzie wyrażenie oznacza pojedyncze wyrażenie, które konwertuje na określony typ.
Jeśli wynik takiej konwersji zakończy się pomyślnie, zwracana jest referencja do typu, w przeciwnym razie referencja pusta. Operator as może być używany tylko do konwersji referencji, tożsamości, pakowania i rozpakowywania. W niektórych przypadkach operator as może być wygodną alternatywą dla operatora is. Jako przykład rozważmy następujący program:
Korzystanie z systemu; przestrzeń nazw ConsoleApplication1 ( class Add ( ) class Sum: Add ( ) class Program ( static void Main() ( Add a = new Add(); Sum s = new Sum(); // Wykonaj rzutowanie typu a = s jako Add; if (a != null) Console.WriteLine("Konwersja powiodła się"); else Console.WriteLine("Błąd podczas konwersji"); Console.ReadLine()) )
Efektem wykonania tego programu będzie pomyślna konwersja.
a = (b > 0) && (c + 1 != d); flaga = !(status = 0);
Tabela 14.5. Operatory logiczne
Opis operatora
! NIE (inwersja logiczna)
&& AND (mnożenie logiczne)
|| LUB (dodatek logiczny)
Tabela 14.6. Wyniki wykonania operatorów AND i OR
Operanda 1 |
Operand 2 |
||
Tabela 14.7. Wyniki wykonania operatora NOT
typ operatora get
Wpisz operator get typeof zwraca ciąg opisujący typ danych operandu. Operand, którego typ chcesz poznać, jest umieszczony po tym operatorze i ujęty w nawiasy:
s = typ("str");
W wyniku wykonania tego wyrażenia zmienna s będzie zawierać ciąg znaków „string” wskazujący typ ciągu.
Wszystkie wartości, które operator typeof może zwrócić, są wymienione w tabeli. 14.8.
Tabela 14.8. Wartości zwracane przez operator typeof |
||
Typ danych |
Ciąg zwrotny |
|
Strunowy |
||
Liczbowy |
||
Tabela 14.8 (koniec) |
|||
Typ danych |
Ciąg zwrotny |
||
Logiczny |
|||
Zgodność i konwersja typów danych
Czas rozważyć jeszcze dwie istotne kwestie: zgodność typów danych i konwersję z jednego typu na drugi.
Co otrzymasz, dodając dwie wartości liczbowe? Zgadza się - kolejna wartość liczbowa. A co jeśli dodasz liczbę i ciąg znaków? Trudno powiedzieć... Tutaj JavaScript boryka się z problemem niezgodnych typów danych i stara się zapewnić kompatybilność tych typów poprzez konwersję jednego z nich na inny. Najpierw próbuje przekonwertować ciąg na liczbę i, jeśli się powiedzie, wykonuje dodawanie. Jeśli operacja się nie powiedzie, liczba zostanie przekonwertowana na ciąg znaków, a dwa powstałe ciągi zostaną połączone. Na przykład uruchomienie skryptu internetowego z Listingu 14.6 spowoduje konwersję wartości b na wartość liczbową po dodaniu do a; zatem zmienna c będzie zawierać wartość 23.
Listowanie 14.6
var a, b, c, d, e, f; a = 11;
b = „12”; do = za + b;
d = "JavaScript"; mi = 2;
Ponieważ jednak wartości zmiennej d nie można przekonwertować na liczbę, wartość e zostanie przekonwertowana na ciąg znaków, a wynik – wartość f – będzie równy
Wartości logiczne są konwertowane na wartości liczbowe lub łańcuchowe, w zależności od konkretnego przypadku. Wartość true zostanie przekonwertowana na liczbę 1 lub ciąg „1” i wartość fałszywa- na 0 lub „0” . I odwrotnie, liczba 1 zostanie przekonwertowana na wartość true, a liczba 0 zostanie przekonwertowana na wartość false. Ponadto wartość false zostanie przekonwertowana na
Mamy wartości null i undefinied .
Część III. Zachowanie strony internetowej. Skrypty internetowe |
|
Można zauważyć, że JavaScript ma trudności z poprawnym wykonaniem nawet źle napisanych wyrażeń. Czasami to działa, ale najczęściej nie wszystko działa zgodnie z planem i ostatecznie wykonanie skryptu WWW zostaje przerwane z powodu wykrycia błędu w zupełnie innym miejscu, na całkowicie poprawnej instrukcji. Dlatego lepiej unikać takich zdarzeń.
Pierwszeństwo operatora
Ostatnią kwestią, którą się tutaj zajmiemy, jest pierwszeństwo operatora. Jak pamiętamy, pierwszeństwo wpływa na kolejność wykonywania operatorów w wyrażeniu.
Niech będzie następujące wyrażenie:
W tym przypadku najpierw do wartości zmiennej b zostanie dodana wartość c, a następnie od sumy zostanie odjęte 10. Operatory tego wyrażenia mają ten sam priorytet i dlatego są wykonywane ściśle od lewej do prawej.
Rozważmy teraz to wyrażenie:
Tutaj wartość c zostanie najpierw pomnożona przez 10, a dopiero potem wartość b zostanie dodana do powstałego iloczynu. Operator mnożenia ma wyższy priorytet niż operator dodawania, więc kolejność „ściśle od lewej do prawej” zostanie zerwana.
Operatory przypisania mają najniższy priorytet. Dlatego najpierw oceniane jest samo wyrażenie, a następnie jego wynik przypisywany jest do zmiennej.
W Ogólnie rzecz biorąc, podstawowa zasada wykonywania wszystkich operatorów jest następująca: najpierw wykonywane są operatory o wyższym priorytecie, a dopiero potem operatory o niższym. Operatory o tym samym priorytecie są wykonywane w kolejności, w jakiej się pojawiają (od lewej do prawej).
W tabela 14.9 zawiera listę wszystkich operatorów, których badaliśmy, w kolejności malejącej według ich priorytetów.
Tabela 14.9. Pierwszeństwo operatora (w kolejności malejącej) |
||
Operatorzy |
Opis |
|
++ -- - ~ ! typ |
Inkrementacja, dekrementacja, zmiana znaku, logiczne NIE, definicja typu |
|
Mnożenie, dzielenie, reszta |
||
Dodawanie i łączenie ciągów znaków, odejmowanie |
||
Operatory porównania |
||
Logiczne AND |
||
Rozdział 14. Wprowadzenie do programowania WWW. Język JavaScript |
|||
Tabela 14.9 (koniec) |
|||
Operatorzy |
Opis |
||
Logiczne LUB |
|||
Instrukcja warunkowa (patrz poniżej) |
|||
= <оператор>= |
Zadanie proste i złożone |
||
UWAGA!
Zapamiętaj tę tabelę. Niewłaściwe wykonanie instrukcji może spowodować trudne do wykrycia błędy, w których pozornie absolutnie poprawne wyrażenie daje błędny wynik.
Ale co, jeśli będziemy musieli złamać normalną kolejność wykonywania instrukcji? Użyjmy nawiasów. Zapisane w ten sposób instrukcje zawarte w nawiasach są wykonywane jako pierwsze:
a = (b + c) * 10;
Tutaj najpierw zostaną dodane wartości zmiennych b i c, a następnie uzyskana suma zostanie pomnożona przez 10.
Operatory ujęte w nawiasy również podlegają pierwszeństwu. Dlatego często stosuje się wiele zagnieżdżonych nawiasów:
a = ((b + c) * 10 - d) / 2 + 9;
Tutaj operatory zostaną wykonane w następującej kolejności:
1. Dodanie b i c.
2. Otrzymaną kwotę pomnóż przez 10.
3. Odejmowanie d od iloczynu.
4. Podziel różnicę przez 2.
5. Dodanie 9 do ilorazu.
Jeśli usuniesz nawiasy:
za = b + do * 10 - d / 2 + 9;
wówczas kolejność wykonywania operatorów będzie następująca:
1. Mnożenie c i 10.
2. Podziel d przez 2.
3. Dodanie b i iloczynu c i 10.
4. Odejmowanie ilorazu z dzielenia od otrzymanej sumy d o 2.
5. Do powstałej różnicy dodaj 9.
Okazuje się, że to zupełnie inny wynik, prawda?
JavaScript Lub JS(w skrócie) nie jest łatwym językiem i początkujący programiści nie nauczą się go od razu. Na początku uczą się podstaw i wszystko wydaje się kolorowe i piękne. Idąc nieco głębiej, pojawiają się Tablice JavaScriptu, obiekty, wywołania zwrotne i wszystko, co często robi na tobie wrażenie.
W JavaScript istotne jest odpowiednie sprawdzenie typu zmiennej. Powiedzmy, że chcesz wiedzieć, czy zmienna jest tablicą, czy obiektem? Jak to sprawdzić prawidłowo? W tym konkretnym przypadku podczas weryfikacji zdarzają się chwyty i o nich będzie ten wpis. Zacznijmy od razu.
Sprawdzanie typu zmiennej
Na przykład musisz sprawdzić, czy zmienna jest obiektem, tablicą, ciągiem znaków lub liczbą. Można do tego użyć typeof, jednak nie zawsze powie to prawdę i na poniższym przykładzie pokażę dlaczego.
Napisałem ten przykład, aby jasno pokazać, dlaczego typeof nie zawsze jest właściwym wyborem.
Var _comparison = ( string: "string", int: 99, float: 13,555, obiekt: (witaj: "witaj"), tablica: new Array(1, 2, 3) ); // Zwraca tablicę zawierającą klucze obiektu var _objKeys = Object.keys(_comparison); for(var i = 0; tj<= _objKeys.length - 1; i++) { // выведем в консоль тип каждой переменной console.log(typeof _comparson[_objKeys[i]]); }
Wynik wykonania kodu:
Obiekt typu string numer obiektu
Prawidłowy? - Oczywiście nie. Są dwa problemy. Każdy z nich zostanie szczegółowo opisany i zaproponowane rozwiązanie.
Pierwszy problem: liczba zmiennoprzecinkowa, wynik jako liczba
Comparison.float nie jest liczbą i liczba powinna być liczbą zmiennoprzecinkową (liczbą zmiennoprzecinkową). Aby temu zaradzić, możesz utworzyć funkcję ze sprawdzaniem, jak w kodzie poniżej.
Var_floatNumber = 9,22; var _notFloatNumber = 9; konsola.log(isFloat(_floatNumber)); konsola.log(isFloat(_notFloatNumber)); konsola.log(isFloat("")); funkcja isFloat(n)( return Number(n) === n && n % 1 !== 0; )
Funkcja isFloat() sprawdza, czy wszystkie wartości są zmiennoprzecinkowe. Najpierw sprawdzane jest, czy zmienna jest równa N liczba (Number(n) === n) i jeśli tak, wówczas przeprowadzana jest kolejna kontrola dzielenia z resztą, a jeśli jest reszta, to wartość logiczna ( PRAWDA Lub FAŁSZ) wynik (n % 1 !== 0).
W powyższym przykładzie powraca PRAWDA, FAŁSZ I FAŁSZ. Pierwsze znaczenie to platforma wpisz, drugi nie - to zwykła liczba, a ostatni to po prostu pusty ciąg znaków, który nie pasuje do reguł.
Drugi problem: tablica została zdefiniowana jako obiekt
W pierwszym przykładzie tablica została wyświetlona jako obiekt, co nie jest zbyt dobre, ponieważ czasami trzeba użyć dokładnie tego typu i niczego innego.
Istnieje kilka sposobów sprawdzenia, czy zmienna jest typem tablicowym.
Pierwsza opcja (dobra opcja). Sprawdzamy, czy dane należą do tablicy, za pomocą instancji().
Var data = new Array("witaj", "świat"); var isArr = instancja danych tablicy;
Opcja druga (dobra opcja). Metoda Array.isArray() zwraca wartość logiczną, która będzie zależała od tego, czy zmienna jest tablicą, czy nie ().
Var data = new Array("witaj", "świat"); var isArr = Array.isArray(dane);
Opcja trzecia (najlepsza, ale długa). Dla wygody możesz uczynić tę metodę funkcją. Używając obiektu, robimy to . Jeśli wynik Object.prototype.toString.call(data) nie jest równy, wówczas zmienna nie jest tablicą ().
Var data = new Array("witaj", "świat"); var isArr = Obiekt.prototype.toString.call(data) == ""; konsola.log(isArr);
Ostatni wynik w postaci funkcji wygody:
Funkcja isArray(data) ( return Object.prototype.toString.call(data) == "" )
Teraz możesz wywołać funkcje isArray() i ustawić tablicę lub coś innego jako argument i zobaczyć wynik.
Posłowie
Nagranie okazało się dość duże, niż pierwotnie zakładano. Ale jestem z niego zadowolony, ponieważ dość zwięźle i jasno opisuje trudności podczas sprawdzania zmiennych w JavaScript i jak je obejść.
Jeśli nadal masz jakieś pytania, napisz je poniżej do tego wpisu. Chętnie pomogę.