JS

typeof vs. instanceof

 

var foo = 'foo';

console.log(typeof foo); //"string"
console.log(foo instanceof String); //false

Wtf?

Operator instanceof zwraca true, jeżeli określony obiekt jest obiektem określonego typu .

Operator typeof zwraca łańcuch zawierający typ operandu. Operand jest łańcuchem znaków, zmienną, słowem kluczowym lub obiektem, którego typ ma zostać zwrócony.

Po polsku proszę.

Operator instanceof  sprawdza, czy dany obiekt jest instancją określonego typu (konstruktora). Innymi słowy – analizuje łańcuch prototypów (prototype chain) i sprawdza, czy dany obiekt został utworzony danym konstruktorem. 

Operator typeof zwraca typ obiektu; sprawdza, czy dany obiekt jest typu prymitywnego (prostego), czy jest czymkolwiek innym (obiektem).

 


 

Wracając do przykładu kodu z samego początku. Czym innym jest literał łańcuchowy, a czym innym klasa String.

var color1 = new String("green"); //ciąg utworzony przy pomocy konstruktora
color1 instanceof String; // true
typeof color1; //object

var color2 = "coral"; //literał łańcuchowy
color2 instanceof String; // false
typeof color2; //string

W JS mamy 5 typów prymitywnych: undefined, null, boolean, string oraz number. Cała reszta to zmienne typu referencyjnego (są obiektami). Oznacza to, że zmienne nie mają przypisanej bezpośrednio wartości, a tylko wskazują na miejsce w pamięci, gdzie te dane są przetrzymywane.
Typy boolean, string oraz number mają swoje obiektowe odpowiedniki. To obiekty, które są instancjami odpowiednio konstruktorów Boolean, String oraz Number.

typeof true; //boolean
typeof new Boolean(true); //object
 
typeof "abc"; //string
typeof new String("abc"); //object
 
typeof 123; //number
typeof new Number(123); //object

 


 

Mało tego. Dla przykładu: wiemy już, że literał łańcuchowy a klasa String to dwa oddzielne byty w JS. Uwaga! Mogę użyć metod metod pochodzących od klasy String na literale, a zadziałają one jakby ten literał był instancją obiektu String. Magia!

String.prototype.returnMe = function() {
 return this;
}
 
var a = "abc";
var b = a.returnMe(); 
 
a; //abc 
typeof a; //string (nadal typ prymitywny)
b; //abc
typeof b; //object

Co widzimy w powyższym przykładzie? JS automatycznie konwertuje typ prosty na obiekt, wywołuje metodę / pobiera właściwość, a następnie przywraca daną zmienną do typu prostego.

Właśnie dzięki temu mechanizmowi możemy np. dobierać się do właściwości .length na literale, mimo iż właściwość ta przynależy do obiektu String.

var abc = 'abc'; //literał
abc.length; //3 - własność obiektu String wywołana na literale

 


 

Mało tego. Dla przykładu obiekt String to także obiekt typu Object.

var myString = new String();
myString instanceof String; // true
myString instanceof Object; // true

Wynika to z dziedziczenia, które jest realizowane przez łańcuch prototypów. Obiekt String został utworzony na bazie prototypu String.prototype. Idąc dalej – prototyp String.prototype też jest obiektem, który powstał na bazie prototypu Object.prototypeObject.prototype jest końcowym elementem łańcucha, nie ma już swojego bazowego prototypu.
Warto też pamiętać, co daje nam dziedziczenie – obiekty potomne mają oprócz cech zdefiniowanych we własnych prototypach również cechy (metody) typów nadrzędnych.

 


 

A jak to wygląda dla innych typów?


 

Źródła:
– dokumentacja: KLIK!KLIK!,
– stackoverflow <3 KLIK!,
– polecam: KLIK!KLIK!KLIK!,
– inne: KLIK!.

Artykuły, które mogą Ci się spodobać...

Wpisz hasło, którego szukasz i naciśnij ENTER, aby je wyszukać. Naciśnij ESC, aby anulować.

Dawaj na górę