var foo = 'foo';
console.log(typeof foo); //"string"
console.log(foo instanceof String); //false
Wtf?
Operator
instanceof
zwracatrue
, 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 jeszcze raz.
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.prototype
. Object.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?
typeof | instanceof | |
---|---|---|
string | typeof "abc"; //string | "abc" instanceof String; //false |
"abc" instanceof Object; //false | ||
number | typeof 5; //number | 5 instanceof Number; // false |
5 instanceof Object; // false | ||
boolean | typeof true; //boolean | true instanceof Boolean; //false |
true instanceof Object; //false | ||
object | typeof {}; //object | {} instanceof Object; //true |
array | typeof []; //object | [] instanceof Array; //true |
RegEx | typeof /regularexpression/; //object | /regularexpression/ instanceof RegExp; //true |
undefined | typeof undefined; //undefined | undefined instanceof Object; //false |
empty (null) | typeof null; //object | null instanceof Object; //false |
NaN | typeof NaN; //number | NaN instanceof Object; //false |
date | typeof new Date(); //object | new Date() instanceof Date; // true |
new Date() instanceof Object; // true | ||
typeof Date; // function | Date instanceof Date; //false | |
Date instanceof Object; //true | ||
function | typeof function() {}; //function | function() {} instanceof Function; //true |
typeof parseInt; //function | parseInt instanceof Function; //true | |
other | typeof Function; //function | Function instanceof Function; //true |
typeof Math; //object | Math instanceof Object; //true | |
typeof String; //function | String instanceof Function; //true | |
custom | var ClassFirst = function () {}; | var ClassFirst = function () {}; |
var instance = new ClassFirst(); | var instance = new ClassFirst(); | |
typeof instance; // object | instance instanceof Object; //true | |
typeof instance == 'ClassFirst'; //false | instance instanceof ClassFirst; //true | |
Źródła:
– dokumentacja: KLIK!, KLIK!,
– stackoverflow <3 KLIK!,
– polecam: KLIK!, KLIK!, KLIK!,
– inne: KLIK!.