Typy referencyjne ECMAScript
- Poprzednia strona Konwersja typów ECMAScript
- Następna strona Jednoargumentowe operator
Typy odniesień są zwykle nazywane klasami (class).
Ten kurs omówi dużą liczbę predefiniowanych typów odniesień w ECMAScript.
Typy odniesień
Typy odniesień są zwykle nazywane klasami (class), co oznacza, że przy napotkaniu wartości odniesienia, przetwarzany jest obiekt.
Ten kurs omówi dużą liczbę predefiniowanych typów odniesień w ECMAScript.
Od teraz, skupimy się na typach odniesień ściśle związanych z już omówionymi typami pierwotnymi.
Uwaga:W tradycyjnym sensie, ECMAScript nie ma naprawdę klas. W rzeczywistości, oprócz wskazywania na to, że klasy nie istnieją, w ECMA-262 nie występuje słowo „klasa”. ECMAScript definiuje „definicję obiektu”, co logicznie jest ekwiwalentne z klasami w innych językach programowania.
Wskazówka:Ten kurs będzie używać terminu "obiekt".
Obiekt jest tworzony za pomocą operatora new oraz nazwy obiektu do zainstalowania. Na przykład, poniższy kod tworzy instancję obiektu Object:
var o = new Object();
Ta składnia jest podobna do języka Java, ale w ECMAScript, gdy jest więcej niż jeden parametr, wymagane są nawiasy. Jeśli nie ma parametrów, jak w poniższym kodzie, nawiasy mogą być pominięte:
var o = new Object;
Uwaga:Choć nawiasy nie są obowiązkowe, lepiej jest używać ich, aby uniknąć zamieszania.
Wskazówka:Będziemy bardziej dogłębnie omawiać obiekty i ich zachowanie w rozdziale podstaw obiektów.
Tematem tego rozdziału są typy referencyjne o równoważnych typach prymitywnych.
Obiekt Object
Obiekt Object nie jest zbyt użyteczny, ale warto go poznać przed poznaniem innych klas. Ponieważ obiekt Object w ECMAScript jest podobny do java.lang.Object w Java, wszystkie obiekty w ECMAScript są od niego dziedziczone, wszystkie właściwości i metody obiektu Object będą pojawiać się w innych obiektach, więc zrozumienie obiektu Object pozwala lepiej zrozumieć inne obiekty.
Obiekt Object ma następujące właściwości:
- constructor
- Odwołanie do funkcji tworzącej obiekt (wskaźnik). Dla obiektu Object, wskaźnik wskazuje na oryginalną funkcję Object().
- Prototype
- Odwołanie do prototypu obiektu. Dla wszystkich obiektów, domyślnie zwraca instancję obiektu Object.
Obiekt Object ma również kilka metod:
- hasOwnProperty(property)
- Sprawdza, czy obiekt ma określoną właściwość. Musi być podana jako ciąg znaków (np. o.hasOwnProperty("name"))
- IsPrototypeOf(object)
- Sprawdza, czy ten obiekt jest prototypem innego obiektu.
- PropertyIsEnumerable
- Sprawdza, czy podana właściwość może być wyliczana za pomocą instrukcji for...in.
- ToString()
- Zwraca oryginalny ciąg znaków obiektu. Dla obiektu Object, ECMA-262 nie definiuje tej wartości, więc różne realizacje ECMAScript mają różne wartości.
- ValueOf()
- Zwraca oryginalną wartość najbardziej odpowiednią dla obiektu. Dla wielu obiektów, wartość zwracana przez tę metodę jest taka sama jak wartość zwracana przez metodę ToString().
Komentarz:Każda wymieniona atrybutów i metod będzie nadpisywana przez inne obiekty.
Obiekt Boolean
Obiekt Boolean jest typem referencyjnym dla oryginalnego typu Boolean.
Aby utworzyć obiekt Boolean, wystarczy przekazać wartość Boolean jako parametr:
var oBooleanObject = new Boolean(true);
Obiekt Boolean nadpisuje metodę ValueOf() obiektu Object, zwracając oryginalną wartość, tj. true i false. Metoda ToString() również jest nadpisana, zwracając ciąg "true" lub "false".
Niestety, w ECMAScript rzadko używa się obiektów Boolean, nawet jeśli są używane, są trudne do zrozumienia.
Problemy zwykle pojawiają się, gdy w wyrażeniach Boolean używa się obiektów Boolean. Na przykład:
var oFalseObject = new Boolean(false); var bResult = oFalseObject && true; //Wynik to true
W tym kodzie, obiekt Boolean jest tworzony z wartością false. Następnie ta wartość jest operacją AND z oryginalną wartością true. W obliczeniach Boolean wynik operacji AND false i true to false. Jednak w tym wierszu kodu, obliczany jest oFalseObject, a nie jego wartość false.
Jak omówiono wcześniej, w wyrażeniach Boolean wszystkich obiektów jest automatycznie konwertowanych na true, więc wartość oFalseObject wynosi true. Następnie true jest operacją AND z true, wynik to true.
Uwaga:Chociaż powinieneś znać dostępność obiektu Boolean, lepiej jest używać oryginalnych wartości Boolean, aby uniknąć problemów omówionych w tym rozdziale.
Zobacz
Aby uzyskać więcej informacji na temat obiektu Boolean, odwiedź Podręcznik referencyjny obiektu Boolean w JavaScript.
Obiekt Number
Jak możesz się spodziewać, obiekt Number jest typem referencyjnym dla oryginalnego typu Number. Aby utworzyć obiekt Number, użyj następującego kodu:
var oNumberObject = new Number(68);
Powinieneś już rozpoznać obiekt Number omówiony w poprzednich sekcjach tego rozdziału (np. Number.MAX_VALUE). Wszystkie specjalne wartości są statycznymi atrybutami obiektu Number.
Aby uzyskać oryginalną wartość Number obiektu, wystarczy użyć metody valueOf():
var iNumber = oNumberObject.valueOf();
Oczywiście, klasa Number również ma metodę toString(), która była szczegółowo omawiana w rozdziale dotyczącym konwersji typów.
Oprócz standardowych metod dziedziczonych z obiektu Number, obiekt Number ma kilka specjalnych metod do przetwarzania liczb.
Metoda toFixed()
Metoda toFixed() zwraca ciąg znaków liczby z określoną liczbą miejsc po przecinku. Na przykład:
var oNumberObject = new Number(68); alert(oNumberObject.toFixed(2)); //wyjście "68.00"
W tym przypadku parametr metody toFixed() wynosi 2, co oznacza, że powinno być wyświetlonych dwa miejsca po przecinku. Metoda ta zwraca "68.00", puste miejsca są wypełniane zerami. Jest bardzo użyteczna w aplikacjach przetwarzających waluty. Metoda toFixed() może reprezentować liczby z 0 do 20 miejsc po przecinku, wartości poza tym zakresem wywołują błąd.
Metoda toExponential()
Inną metodą formatowania liczb jest metoda toExponential(), która zwraca ciąg znaków liczby w formie wykładniczej.
Podobnie jak metoda toFixed(), metoda toExponential() również ma parametr, który określa liczbę miejsc po przecinku do wyświetlenia. Na przykład:
var oNumberObject = new Number(68); alert(oNumberObject.toExponential(1)); //wyjście "6.8e+1"
Wynik tego kodu to "6.8e+1", jak już wyjaśniono, oznacza to 6.8x101Problem polega na tym, co zrobić, jeśli nie wiadomo, w jakiej formie (zdefiniowanej lub wykładniczej) przedstawić liczbę? Można użyć metody toPrecision().
Metoda toPrecision()
Metoda toPrecision() zwraca zdefiniowaną formę lub formę wykładniczą liczby w zależności od najbardziej znaczącej formy. Ma jeden parametr, który określa liczbę cyfr używanych do przedstawienia liczby (bez wykładnika). Na przykład,
var oNumberObject = new Number(68); alert(oNumberObject.toPrecision(1)); //wyjście "7e+1"
Zadaniem tego kodu jest przedstawienie liczby 68 za pomocą jednej cyfry, wynik to "7e+1", w innej formie to 70. Tak naprawdę, metoda toPrecision() runda liczby.
var oNumberObject = new Number(68); alert(oNumberObject.toPrecision(2)); //wyjście "68"
Oczywiście, wyjście to "68", ponieważ to dokładne przedstawienie liczby. Ale co, jeśli liczba miejsc po przecinku jest większa niż potrzebne?
var oNumberObject = new Number(68); alert(oNumberObject.toPrecision(3)); // wyświetla "68.0"
W tym przypadku toPrecision(3) jest równoważne z toFixed(1), wyświetla "68.0".
Metody toFixed(), toExponential() i toPrecision() przeprowadzają operacje zaokrąglania, aby poprawnie wyświetlić liczbę z odpowiednią liczbą miejsc po przecinku.
Wskazówka:Podobnie jak obiekt Boolean, obiekt Number jest bardzo ważny, ale powinien być używany rzadziej, aby uniknąć potencjalnych problemów. W miarę możliwości, używaj oryginalnych reprezentacji liczb.
Zobacz
Aby uzyskać więcej informacji na temat obiektu Number, odwiedź Podręcznik referencyjny obiektu Number w JavaScript.
Obiekt String
Obiekt String jest reprezentacją obiektu typu String, który jest tworzony w następujący sposób:
var oStringObject = new String("hello world");
Metody valueOf() i toString() obiektu String zwracają oryginalną wartość typu String:
alert(oStringObject.valueOf() == oStringObject.toString()); // wyświetla "true"
Jeśli uruchomisz ten kod, wynik to "true", co oznacza, że te wartości są rzeczywiście równe.
Komentarz:Obiekt String jest jednym z bardziej złożonych typów odwołujących się w ECMAScript. W tym rozdziale skupiamy się tylko na podstawowych funkcjach klasy String. Więcej zaawansowanych funkcji znajdziesz w odpowiednich rozdziałach tego podręcznika, lub zapoznaj się z Podręcznik referencyjny obiektu String w JavaScript.
Właściwość length
Obiekt String ma właściwość length, która jest liczbą znaków w ciągu:
var oStringObject = new String("hello world"); alert(oStringObject.length); // wyświetla "11"
Ten przykład wyświetla "11", co oznacza liczbę znaków w "hello world". Zwróć uwagę, że nawet jeśli ciąg zawiera dwubajtowe znaki (w przeciwieństwie do znaków ASCII, które zajmują tylko jeden bajt), każdy znak jest liczony jako pojedynczy znak.
Metody charAt() i charCodeAt()
Obiekt String ma również wiele metod.
Po pierwsze, obie metody charAt() i charCodeAt() dostępują pojedyncze znaki w ciągu. Obie metody mają jeden parametr, który jest pozycją operowanego znaku.
charAt() metoda zwraca ciąg znaków zawierający znak na określonej pozycji:
var oStringObject = new String("hello world"); alert(oStringObject.charAt(1)); // wyświetla "e"
W stringu "hello world", znak na pozycji 1 to "e". W sekcji "ECMAScript primitive types" omówiliśmy, że pozycja pierwszego znaku wynosi 0, pozycja drugiego znaku wynosi 1, itd. Dlatego wywołanie charAt(1) zwraca "e".
Jeśli nie chcemy uzyskać znaku, ale kodu znaku, możemy wywołać metodę charCodeAt():
var oStringObject = new String("hello world"); alert(oStringObject.charCodeAt(1)); // wyświetla "101"
Ten przykład wyświetla "101", co jest kodem znaku małej litery "e". W sekcji "ECMAScript primitive types" omówiliśmy, że pozycja pierwszego znaku wynosi 0, pozycja drugiego znaku wynosi 1, itd. Dlatego wywołanie charAt(1) zwraca "e".
Metoda concat()
Następna metoda to concat(), która służy do dodania jednego lub kilku stringów do oryginalnej wartości obiektu String. Metoda ta zwraca oryginalną wartość String, pozostawiając oryginalny obiekt String niezmienny:
var oStringObject = new String("hello "); var sResult = oStringObject.concat("world"); alert(sResult); // wyświetla "hello world" alert(oStringObject); // wyświetla "hello "
W tym kodzie, wywołanie metody concat() zwraca "hello world", podczas gdy obiekt String przechowuje nadal "hello ". Z tego powodu, bardziej powszechnym jest łączenie stringów za pomocą plusa (+), ponieważ ta forma logicznie wskazuje prawdziwe zachowanie:
var oStringObject = new String("hello "); var sResult = oStringObject + "world"; alert(sResult); // wyświetla "hello world" alert(oStringObject); // wyświetla "hello "
Metody indexOf() i lastIndexOf()
Do tej pory omówiliśmy metody łączenia stringów oraz metody dostępu do pojedynczych znaków w stringu. Ale co zrobić, jeśli nie wiadomo, czy dany znak rzeczywiście istnieje w stringu? W takim przypadku można użyć metod indexOf() i lastIndexOf().
Metody indexOf() i lastIndexOf() zwracają pozycję określonego podciągu w innym stringu. Jeśli podciąg nie został znaleziony, zwracana jest wartość -1.
Różnica między tymi metodami polega na tym, że indexOf() metoda zaczyna wyszukiwanie ciągu w stringu od początku (pozycja 0), podczas gdy lastIndexOf() metoda zaczyna od końca stringu. Na przykład:
var oStringObject = new String("hello world!"); alert(oStringObject.indexOf("o")); // wyświetla "4" alert(oStringObject.lastIndexOf("o")); // wyświetla "7"
Tutaj, pierwsza "o" w ciagu znaków "o" znajduje się na pozycji 4, tj. w "hello"; ostatnia "o" znajduje się na pozycji 7, tj. w "world". Jeśli ciąg znaków zawiera tylko jedną "o", to pozycje zwracane przez metody indexOf() i lastIndexOf() są takie same.
Metoda localeCompare()
Następna metoda to localeCompare(), która sortuje ciągi znaków. Metoda ta ma jeden parametr - ciąg znaków do porównania, zwraca jedną z trzech wartości poniżej:
- Jeśli obiekt String jest uporządkowany alfabetycznie przed ciągiem znaków w parametrze, zwraca wartość ujemną.
- Jeśli obiekt String jest równy ciągowi znaków w parametrze, zwraca wartość 0
- Jeśli obiekt String jest uporządkowany alfabetycznie po ciągu znaków w parametrze, zwraca wartość dodatnią.
Komentarz:Jeśli zwracana wartość jest ujemna, to najczęściej jest to -1, ale rzeczywiście zwracana wartość jest przez implementację. Jeśli zwracana wartość jest dodatnia, to tak samo, najczęściej jest to 1, ale rzeczywiście zwracana wartość jest przez implementację.
Poniżej znajduje się przykład:
var oStringObject = new String("yellow"); alert(oStringObject.localeCompare("brick")); // wyświetla "1" alert(oStringObject.localeCompare("yellow")); // wyświetla "0" alert(oStringObject.localeCompare("zoo")); // wyświetla "-1"
W tym kodzie, ciąg znaków "yellow" został porównany z 3 wartościami, tj. "brick", "yellow" i "zoo". Ponieważ są one uporządkowane alfabetycznie, "yellow" znajduje się po "brick", więc localeCompare() zwraca 1; "yellow" jest równe "yellow", więc localeCompare() zwraca 0; "zoo" znajduje się po "yellow", localeCompare() zwraca -1. Podkreślam to jeszcze raz, ponieważ wartości zwracane są przez implementację, najlepiej wywoływać metodę localeCompare() w następujący sposób:
var oStringObject1 = new String("yellow"); var oStringObject2 = new String("brick"); var iResult = oStringObject1.localeCompare(oStringObject2); if(iResult < 0) { alert(oStringObject1 + " idzie przed " + oStringObject2); } alert(oStringObject1 + " idzie po " + oStringObject2); } alert("Dwa stringi są równe"); }
Dzięki tej strukturze można zapewnić, że ten kod będzie działał poprawnie we wszystkich implementacjach.
Unikalność metody localeCompare() polega na tym, że lokalizacja (locale, obejmująca kraj/region i język) dokładnie określa sposób działania tej metody. W Stanach Zjednoczonych angielski jest standardowym językiem implementacji ECMAScript, localeCompare() jest rozróżniający wielkość liter, gdzie duże litery są porządkowane po małych literach. Jednak w innych lokalizacjach może to wyglądać inaczej.
slice() i substring()
ECMAScript oferuje dwa metody do tworzenia wartości string z podciagu, tj. slice() i substring(). Oba metody zwracają podciag do przetwarzania stringu, przyjmują jeden lub dwa parametry. Pierwszy parametr to pozycja początkowa podciagu, drugi parametr (jeśli jest używany) to pozycja końcowa podciagu (czyli znak w pozycji końcowej nie jest uwzględniany w zwracanej wartości). Jeśli pominięto drugi parametr, pozycja końcowa jest domyślnie ustawiona na długość stringu.
Jak funkcja concat(), metody slice() i substring() nie zmieniają wartości obiektu String. Zwracają jedynie oryginalną wartość String, pozostawiając obiekt String niezmienny.
var oStringObject = new String("hello world"); alert(oStringObject.slice("3")); // Wyjście "lo world" alert(oStringObject.substring("3")); // Wyjście "lo world" alert(oStringObject.slice("3", "7")); // Wyjście "lo w" alert(oStringObject.substring("3", "7")); // Wyjście "lo w"
W tym przykładzie, funkcje slice() i substring() są używane w ten sam sposób i zwracają takie same wartości. Gdy parametr wynosi 3, obie funkcje zwracają "lo world", ponieważ drugi "l" w "hello" znajduje się na pozycji 3. Gdy parametry wynoszą 3 i 7, obie funkcje zwracają "lo w" (litera "o" w "world" znajduje się na pozycji 7, więc nie jest włączone do wyniku).
Dlaczego istnieją dwa funkcje o takim samym działaniu? W rzeczywistości, te dwie funkcje nie są zupełnie takie same, chociaż różnią się tylko w sposobie przetwarzania parametrów, gdy są one ujemne.
Dla ujemnych parametrów, funkcja slice() dodaje wartość parametru do długości ciągu, podczas gdy funkcja substring() traktuje go jako 0 (czyli go ignoruje). Na przykład:
var oStringObject = new String("hello world"); alert(oStringObject.slice("-3")); // Wyjście "rld" alert(oStringObject.substring("-3")); // Wyjście "hello world" alert(oStringObject.slice("3, -4")); // Wyjście "lo w" alert(oStringObject.substring("3, -4")); // Wyjście "hel"
W ten sposób można zobaczyć główną różnicę między funkcjami slice() i substring().
Gdy tylko parametr -3 jest używany, funkcja slice() zwraca "rld", podczas gdy substring() zwraca "hello world". Powodem tego jest to, że dla ciągu "hello world", slice("-3") jest przekształcane na slice("8"), a substring("-3") na substring("0").
Także, przy użyciu parametrów 3 i -4, różnice są bardzo wyraźne. Funkcja slice() zostanie przekształcona na slice(3, 7), jak w poprzednim przykładzie, zwracając "lo w". Funkcja substring() zaś interpretuje dwa parametry jako substring(3, 0), co w rzeczywistości jest substring(0, 3), ponieważ substring() zawsze traktuje mniejszą liczbę jako pozycję początkową, a większą jako pozycję końcową. Dlatego substring("3, -4") zwraca "hel". Ostatnia linia kodu służy do wyjaśnienia, jak używać tych metod.
toLowerCase(), toLocaleLowerCase(), toUpperCase() i toLocaleUpperCase()
Ostatni zestaw metod do omówienia dotyczy konwersji wielkości liter. Są 4 metody do wykonywania konwersji wielkości liter, tj.
- toLowerCase()
- toLocaleLowerCase()
- toUpperCase()
- toLocaleUpperCase()
Jak sugeruje ich nazwa, pierwsze dwa metody są używane do konwersji ciągów znaków na małe litery, a ostatnie dwa metody są używane do konwersji ciągów znaków na duże litery.
Metody toLowerCase() i toUpperCase() są oryginalne i są zaimplementowane na podstawie metod z java.lang.String.
Metody toLocaleLowerCase() i toLocaleUpperCase() są zaimplementowane na podstawie specyficznych regionów (tak jak w przypadku metody localeCompare()). W wielu regionach, metody specyficzne dla regionu są identyczne z metodami ogólnymi. Jednak kilka języków stosuje specyficzne reguły dla konwersji wielkości znaków Unicode (np. turecki), więc należy używać metod specyficznych dla regionu, aby wykonać poprawną konwersję.
var oStringObject = new String("Hello World"); alert(oStringObject.toLocaleUpperCase()); // wyświetla "HELLO WORLD" alert(oStringObject.toUpperCase()); // wyświetla "HELLO WORLD" alert(oStringObject.toLocaleLowerCase()); // wyświetla "hello world" alert(oStringObject.toLowerCase()); // Wyjście "hello world"
W tym kodzie,toUpperCase() i toLocaleUpperCase() wyświetlają "HELLO WORLD", atoLowerCase() i toLocaleLowerCase() wyświetlają "hello world". Ogólnie rzecz biorąc, jeśli nie wiesz, w jakim kodowaniu działa język, bezpieczniej jest używać metod specyficznych dla regionu.
Wskazówka:Pamiętaj, że wszystkie atrybuty i metody obiektu String mogą być zastosowane do wartości podstawowych String, ponieważ są to pseudoobiekty.
Operator instanceof
Korzystanie z operatora typeof przy przechowywaniu wartości w typach referencyjnych może prowadzić do problemu, niezależnie od typu obiektu, który jest przechowywany, zawsze zwraca "object". ECMAScript wprowadził inny operator Java instanceof, aby rozwiązać ten problem.
Operator instanceof jest podobny do operatora typeof, służy do identyfikacji typu obiektu, z którym pracujemy. W przeciwieństwie do metody typeof, metoda instanceof wymaga, aby deweloper wyraźnie potwierdził, że obiekt jest konkretnego typu. Na przykład:
var oStringObject = new String("hello world"); alert(oStringObject instanceof String); // Wyjście "true"
To kod pyta: "Czy zmienna oStringObject jest instancją obiektu String?" oStringObject rzeczywiście jest instancją obiektu String, więc wynik to "true". Chociaż jest mniej elastyczny niż metoda typeof, metoda instanceof jest bardzo przydatna, gdy metoda typeof zwraca "object".
- Poprzednia strona Konwersja typów ECMAScript
- Następna strona Jednoargumentowe operator