Jak sprawdzić, czy wartość jest obiektem w JavaScript?
Jak sprawdzić, czy wartość jest obiektem w JavaScript?
Odpowiedzi:
AKTUALIZACJA :
Ta odpowiedź jest niepełna i daje mylące wyniki . Na przykład, w JavaScript null
jest również brany pod uwagę rodzaj tekstu object
, nie wspominając o kilku innych przypadkach krawędzi. Postępuj zgodnie z poniższymi zaleceniami i przejdź do innej „najbardziej pozytywnej (i poprawnej!) Odpowiedzi” .
Oryginalna odpowiedź :
Spróbuj użyć typeof(var)
i / lub var instanceof something
.
EDIT: Ta odpowiedź daje wyobrażenie o tym, jak zbadać właściwości zmienna, ale to nie recepta kuloodporne (w końcu nie ma przepis w ogóle!) W celu sprawdzenia, czy jest to obiekt, z dala od niego. Ponieważ ludzie zwykle szukają czegoś do skopiowania stąd bez przeprowadzania badań, zdecydowanie polecam skorzystanie z drugiej, najbardziej pozytywnej (i poprawnej!) Odpowiedzi.
typeof
jest operatorem, więc nie ma takiej potrzeby ()
.
typeof
zwraca „obiekt” dla wartości null, która nie jest obiektem i instanceof
nie działa dla obiektów utworzonych przy użyciu Object.create(null)
.
Jeśli typeof yourVariable === 'object'
jest to obiekt lub zero. Jeśli chcesz wykluczyć null, po prostu zrób to typeof yourVariable === 'object' && yourVariable !== null
.
yourVariable !== null
lepsza praktyka?
typeof null == 'object'
nie zostanie to naprawione w ES6 . Powiedzieli:This proposal has been rejected. It was implemented in V8 but it turned out that it broke a lot of existing sites. In the spirit of One JavaScript this is not feasible.
typeof
ponieważ zawiera ona kilka specjalnych przypadków, które niekoniecznie mają sens. Jeśli próbujesz rozróżnić tablice od obiektów, które nie są tablicami, zdecydowanie nie chcesz używać typeof
.
Object.prototype.toString.call(yourVar)
, będąc Twoim Variem, co musisz sprawdzić. W przypadku tablic Object.prototype.toString.call([1,2])
zwroty[object Array]
Zdefiniujmy „obiekt” w JavaScript . Według dokumentów MDN każda wartość jest albo obiektem, albo prymitywem:
pierwotna, pierwotna wartość
Dane, które nie są przedmiotem i nie mają żadnych metod. JavaScript ma 5 prymitywnych typów danych: ciąg, liczba, wartość logiczna, null, niezdefiniowana.
Co to jest prymitywne?
3
'abc'
true
null
undefined
Co to jest obiekt (tzn. Nie prymityw)?
Object.prototype
Object.prototype
Function.prototype
Object
Function
function C(){}
- funkcje zdefiniowane przez użytkownikaC.prototype
- własność prototypu funkcji zdefiniowanej przez użytkownika: nie jest toC
prototyp
new C()
- „nowy” - funkcja zdefiniowana przez użytkownikaMath
Array.prototype
{"a": 1, "b": 2}
- obiekty utworzone za pomocą notacji dosłownejnew Number(3)
- owija się wokół prymitywówObject.create(null)
Object.create(null)
Jak sprawdzić, czy wartość jest obiektem
instanceof
sam w sobie nie zadziała, ponieważ pomija dwa przypadki:
// oops: isObject(Object.prototype) -> false
// oops: isObject(Object.create(null)) -> false
function isObject(val) {
return val instanceof Object;
}
typeof x === 'object'
nie będzie działać z powodu fałszywych alarmów ( null
) i fałszywych negatywów (funkcje):
// oops: isObject(Object) -> false
function isObject(val) {
return (typeof val === 'object');
}
Object.prototype.toString.call
nie będzie działać z powodu fałszywych trafień dla wszystkich prymitywów:
> Object.prototype.toString.call(3)
"[object Number]"
> Object.prototype.toString.call(new Number(3))
"[object Number]"
Więc używam:
function isObject(val) {
if (val === null) { return false;}
return ( (typeof val === 'function') || (typeof val === 'object') );
}
@ Odpowiedź Daana również wydaje się działać:
function isObject(obj) {
return obj === Object(obj);
}
ponieważ zgodnie z dokumentami MDN :
Konstruktor obiektów tworzy opakowanie obiektu dla podanej wartości. Jeśli wartość jest pusta lub niezdefiniowana, utworzy i zwróci pusty obiekt, w przeciwnym razie zwróci obiekt typu odpowiadającego podanej wartości. Jeśli wartość jest już obiektem, zwróci wartość.
Trzecim sposobem, który wydaje się działać (nie jestem pewien, czy to w 100%) jest użycie, Object.getPrototypeOf
które zgłasza wyjątek, jeśli jego argument nie jest obiektem:
// these 5 examples throw exceptions
Object.getPrototypeOf(null)
Object.getPrototypeOf(undefined)
Object.getPrototypeOf(3)
Object.getPrototypeOf('abc')
Object.getPrototypeOf(true)
// these 5 examples don't throw exceptions
Object.getPrototypeOf(Object)
Object.getPrototypeOf(Object.prototype)
Object.getPrototypeOf(Object.create(null))
Object.getPrototypeOf([])
Object.getPrototypeOf({})
obj === Object(obj)
zwraca true
tablice.
var x = []; console.log(x === Object(x)); // return true
getPrototypeOf
nie działa np. z odwołanymi serwerami proxy, które są obiektami, ale rzucają.
({}).toString.apply(obj) === '[object Object]'
rozróżnia tablic od obiektów, które nie są tablicami
underscore.js zapewnia następującą metodę, aby dowiedzieć się, czy coś jest naprawdę obiektem:
_.isObject = function(obj) {
return obj === Object(obj);
};
AKTUALIZACJA
Ze względu na poprzedni błąd w wersji V8 i drobną optymalizację mikro prędkości, metoda wygląda następująco od wersji underscore.js 1.7.0 (sierpień 2014):
_.isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
null
też. Powinna być zaakceptowana odpowiedź.
Object.prototype.toString.call(myVar)
wróci:
"[object Object]"
jeśli myVar jest obiektem"[object Array]"
jeśli myVar jest tablicąAby uzyskać więcej informacji na ten temat i dlaczego jest to dobra alternatywa dla typeof, sprawdź ten artykuł .
typeof [] === 'object'
-> true
. Właśnie tego potrzebujesz.
Object.prototype.toString.call(3)
-> "[object Number]"
. Object.prototype.toString.call(new Number(3))
-> "[object Number]
"
getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
Do prostego sprawdzania względem Object lub Array bez dodatkowego wywołania funkcji (speed). Jak również zamieszczono tutaj .
isArray ()
isArray = function(a) {
return (!!a) && (a.constructor === Array);
};
console.log(isArray( )); // false
console.log(isArray( null)); // false
console.log(isArray( true)); // false
console.log(isArray( 1)); // false
console.log(isArray( 'str')); // false
console.log(isArray( {})); // false
console.log(isArray(new Date)); // false
console.log(isArray( [])); // true
isObject () - Uwaga: używaj tylko dla literałów obiektowych, ponieważ zwraca wartość false dla obiektów niestandardowych, takich jak nowa data lub nowy obiekt YourCustomObject.
isObject = function(a) {
return (!!a) && (a.constructor === Object);
};
console.log(isObject( )); // false
console.log(isObject( null)); // false
console.log(isObject( true)); // false
console.log(isObject( 1)); // false
console.log(isObject( 'str')); // false
console.log(isObject( [])); // false
console.log(isObject(new Date)); // false
console.log(isObject( {})); // true
isObject
działa tylko z literałami obiektowymi. Jeśli utworzę niestandardowy typ, utwórz instancję tego typu i przetestuj go, zwracafalse
Boolean(a)
jest dłuższy, ale o wiele bardziej intuicyjny. Po prostu nie używaj new Boolean(a)
: ( oto dlaczego )!
{
znaku. W przypadku tablicy, o ile nie potrzebujesz obsługi IE <9, możesz użyć, Array.isArray()
aby ustalić, czy coś jest tablicą. Pomija wszystkie podane przez Ciebie przypadki testowe.
Lubię po prostu:
function isObject (item) {
return (typeof item === "object" && !Array.isArray(item) && item !== null);
}
Jeśli element jest obiektem JS i nie jest tablicą JS, i nie jest null
… jeśli wszystkie trzy okażą się prawdziwe, wróć true
. Jeśli którykolwiek z tych trzech warunków zakończy się niepowodzeniem, &&
test spowoduje zwarcie i false
zostanie zwrócony. W null
razie potrzeby test można pominąć (w zależności od sposobu użytkowania null
).
DOCS:
http://devdocs.io/javascript/operators/typeof
http://devdocs.io/javascript/global_objects/object
new Date()
zwraca obiekt. Tablica z logicznego punktu widzenia nie jest obiektem - chociaż JavaScript obsługuje je i zgłasza jako takie. W praktyce jednak nie jest pomocne, aby były one równe, ponieważ nie są. Obiekt nie ma length
na przykład atrybutu i nie ma metod takich jak push (). A czasem możesz chcieć nadać funkcji przeciążone parametry, w których musisz wprowadzić różnicę między tablicą lub obiektem, zwłaszcza jeśli inne parametry zależą od tego, który został podany.
length
właściwości ani metod podobnych do tego push
, Object.create(Array.prototype)
jest banalnym przeciw-przykładem obiektu niebędącego macierzą, który je ma. Cechą wyróżniającą tablice jest to, że są to obiekty egzotyczne z niestandardową, wewnętrzną metodą [[DefineOwnProperty]], ale nadal są obiektami.
length
właściwości (miałem na myśli, że literały obiektowe length
domyślnie nie mają atrybutów). Napisałem, że tablice nie są obiektami z logicznego punktu widzenia. Mówię o logice programu. Czasami konieczne jest sprawdzenie, czy tablica jest „rzeczywistą” tablicą, a na pewno nie „prawdziwym” obiektem. Po to Array.isArray()
jest. Wyobraź sobie, że masz funkcję, która akceptuje obiekt lub tablicę obiektów. Sprawdzanie specjalnego atrybutu lub metody jest brudnym rozwiązaniem. Rodzimy sposób jest zawsze lepszy.
typeof null
jest "object"
, nie "undefined"
.
Array.isArray
:function isObject(o) {
return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}
Array.isArray
:Zaskoczyło mnie tylko, ile głosów za błędnymi odpowiedziami 😮
Tylko 1 odpowiedź przeszła moje testy !!! Tutaj stworzyłem moją uproszczoną wersję:
function isObject(o) {
return o instanceof Object && o.constructor === Object;
}
Jeśli chodzi o mnie, jest to jasne i proste i po prostu działa! Oto moje testy:
console.log(isObject({})); // Will return: true
console.log(isObject([])); // Will return: false
console.log(isObject(null)); // Will return: false
console.log(isObject(/.*/)); // Will return: false
console.log(isObject(function () {})); // Will return: false
JESZCZE WIĘCEJ: nie wszystkie odpowiedzi zdają ten test !!! 🙈
Jeśli musisz zweryfikować, że obiekt jest instancją określonej klasy , musisz sprawdzić konstruktor z określoną klasą, na przykład:
function isDate(o) {
return o instanceof Object && o.constructor === Date;
}
prosty test:
var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d)); // Will return: true
W rezultacie będziesz mieć ścisły i solidny kod!
W przypadku, gdy nie będzie tworzyć funkcje takie jak isDate
, isError
, isRegExp
itp można rozważyć opcję, aby korzystać z tej funkcji uogólnionych:
function isObject(o) {
return o instanceof Object && typeof o.constructor === 'function';
}
nie będzie działać poprawnie dla wszystkich wspomnianych wcześniej przypadków testowych, ale jest wystarczająco dobry dla wszystkich obiektów (prostych lub skonstruowanych).
isObject
nie będzie działać w przypadku, Object.create(null)
ponieważ Object.create
wyjaśniono tutaj wewnętrzne wdrożenie , ale można użyć isObject
bardziej zaawansowanego wdrożenia:
function isObject(o, strict = true) {
if (o === null || o === undefined) {
return false;
}
const instanceOfObject = o instanceof Object;
const typeOfObject = typeof o === 'object';
const constructorUndefined = o.constructor === undefined;
const constructorObject = o.constructor === Object;
const typeOfConstructorObject = typeof o.constructor === 'function';
let r;
if (strict === true) {
r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
} else {
r = (constructorUndefined || typeOfConstructorObject);
}
return r;
};
Jest już utworzony pakiet na npm v1 w oparciu o tę implementację! I działa dla wszystkich wcześniej opisanych przypadków testowych! 🙂
isDate
swojego obiektu DataDbject w celu napisania solidnego kodu, w przeciwnym razie będziesz mieć kruchą isObject
metodę.
Date
w moim komentarzu zostało źle wybrane, ponieważ tak, odpowiedź dyskutuje Date
. Ale Date
jest to tylko jedna z nieskończonych możliwych klas i ta sama zasada dotyczy każdej innej klasy. Przykład: class Foo() { }; var x = new Foo(); isObject(x)
zwraca false
. Nie wiem dokładnie, jaki jest przypadek użycia OP, ale łatwo jest wyobrazić sobie scenariusze, w których znajomość wszystkich możliwych klas i porównanie z każdą z nich będzie niemożliwe.
O mój Boże! Myślę, że może to być krótsze niż kiedykolwiek, zobaczmy to:
function isObject(obj)
{
return obj != null && obj.constructor.name === "Object"
}
console.log(isObject({})) // returns true
console.log(isObject([])) // returns false
console.log(isObject(null)) // returns false
null
Zwraca typy obiektów JavaScript (w tym )"object"
console.log(typeof null, typeof [], typeof {})
Sprawdzanie constructor
właściwości zwraca funkcję z ich nazwami.
console.log(({}).constructor) // returns a function with name "Object"
console.log(([]).constructor) // returns a function with name "Array"
console.log((null).constructor) //throws an error because null does not actually have a property
Function.name
zwraca tylko do odczytu nazwę funkcji lub "anonymous"
dla zamknięć.
console.log(({}).constructor.name) // returns "Object"
console.log(([]).constructor.name) // returns "Array"
console.log((null).constructor.name) //throws an error because null does not actually have a property
Uwaga: od 2018 roku Function.name może nie działać w IE https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility
Object.create(null)
i dlaczego miałbyś to zrobić mimo wszystko ...?
OK, niech daje to pojęcie zanim odpowiadając na pytanie, w funkcji JavaScript Object są również null, Object, macierze i nawet data, tak jak widać jest nie prosty sposób jak typeof obj === „obiektu”, tak wszystko wspomniane powyżej zwróci prawdę , ale istnieją sposoby, aby to sprawdzić, pisząc funkcję lub używając ram JavaScript, OK:
Teraz wyobraź sobie, że masz ten obiekt, który jest prawdziwym obiektem (nie ma wartości null, funkcji lub tablicy):
var obj = {obj1: 'obj1', obj2: 'obj2'};
Czysty JavaScript:
//that's how it gets checked in angular framework
function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
lub
//make sure the second object is capitalised
function isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
lub
function isObject(obj) {
return obj.constructor.toString().indexOf("Object") > -1;
}
lub
function isObject(obj) {
return obj instanceof Object;
}
Możesz po prostu użyć jednej z powyższych funkcji w kodzie, wywołując je, a zwróci true, jeśli jest to obiekt:
isObject(obj);
Jeśli używasz frameworka JavaScript, zwykle przygotowali dla Ciebie tego rodzaju funkcje, jest ich kilka:
jQuery:
//It returns 'object' if real Object;
jQuery.type(obj);
Kątowy:
angular.isObject(obj);
Podkreślenie i Lodash:
//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);
To zależy od tego, co masz na myśli przez „jest przedmiotem”. Jeśli chcesz wszystkiego, co nie jest prymitywne , tj. Rzeczy, na których możesz ustawić nowe właściwości, powinno to załatwić sprawę:
function isAnyObject(value) {
return value != null && (typeof value === 'object' || typeof value === 'function');
}
Wyklucza ona prymitywów (numery zwykły / NaN
/ Infinity
, gładkie stringi, symbole, true
/ false
, undefined
i null
), ale powinien wrócić prawdziwe dla wszystkiego innego (w tym Number
, Boolean
oraz String
obiektów). Zauważ, że JS nie określa, jakie obiekty „hosta”, takie jak window
lub console
, powinny być zwracane, gdy są używane ztypeof
, więc trudno jest je pokryć takim czekiem.
Jeśli chcesz wiedzieć, czy coś jest „zwykłym” obiektem, tj. Zostało utworzone dosłownie, {}
czy za pomocą Object.create(null)
, możesz to zrobić:
function isPlainObject(value) {
if (Object.prototype.toString.call(value) !== '[object Object]') {
return false;
} else {
var prototype = Object.getPrototypeOf(value);
return prototype === null || prototype === Object.prototype;
}
}
Edycja 2018 : Ponieważ Symbol.toStringTag
teraz pozwala dostosować dane wyjściowe Object.prototype.toString.call(...)
, isPlainObject
powyższa funkcja może false
w niektórych przypadkach powrócić, nawet jeśli obiekt zaczął działać jako literał. Prawdopodobnie, zgodnie z konwencją, obiekt z niestandardowym znacznikiem łańcuchowym nie jest już dokładnie zwykłym obiektem, ale to jeszcze bardziej utrudnia definicję tego, czym jest zwykły obiekt w JavaScript.
instanceof Object
dwa identyczne literały funkcji nie są ściśle równe, są przekazywane przez odniesienie itp.
Mój Boże, za dużo zamieszania w innych odpowiedziach.
Krótka odpowiedź
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array)
Aby to przetestować, po prostu uruchom następujące instrukcje w konsoli Chrome.
Przypadek 1.
var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true
Przypadek 2.
anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false
Przypadek 3.
anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false
Wyjaśnienie
Okej, załamajmy się
typeof anyVar == 'object'
jest zwracany jako prawdziwy od trzech kandydatów - [], {} and null
,
anyVar instanceof Object
zawęża tych kandydatów do dwóch - [], {}
!(anyVar instanceof Array)
zawęża się do jednego - {}
Rolki bębna proszę!
Dzięki temu mogłeś już nauczyć się sprawdzać tablicę w JavaScript.
false
(zgodnie z życzeniem), gdy anyVar
jest funkcją.
Najbardziej rozsądnym sposobem sprawdzenia rodzaju wartości wydaje się typeof
operator. Jedynym problemem jest to, że jest strasznie zepsuty:
"object"
zanull
, który należy do typu Null."function"
obiekty, które można wywołać, które należą do typu Object."unknown"
. Jedynymi niedozwolonymi wynikami są "function"
i prymitywne typy.typeof
jest niezawodny tylko w przypadku innych niż null
prymitywne. Zatem sposobem sprawdzenia, czy wartość jest obiektem, byłoby upewnienie się, że zwracany ciąg typeof
nie odpowiada prymitywowi, a obiekt nie jest null
. Problem polega jednak na tym, że przyszły standard mógłby wprowadzić nowy typ pierwotny, a nasz kod uznałby go za obiekt. Nowe typy nie pojawiają się często, ale na przykład ECMAScript 6 wprowadził typ symbolu.
Dlatego zamiast typeof
polecam tylko podejścia, których wynik różni się w zależności od tego, czy wartość jest obiektem, czy nie. Następujące ma być
Object
konstruktor
Object
Konstruktor wymusza przekazany argument do obiektu. Jeśli jest to już obiekt, zwracany jest ten sam obiekt.
Dlatego można go użyć do przymuszenia wartości do obiektu i ścisłego porównania tego obiektu z wartością oryginalną.
Następująca funkcja wymaga ECMAScript 3, który wprowadził ===
:
function isObject(value) { /* Requires ECMAScript 3 or later */
return Object(value) === value;
}
Podoba mi się to podejście, ponieważ jest proste i samoopisujące, a analogiczna kontrola będzie również działać w przypadku logicznych, liczb i ciągów znaków. Należy jednak pamiętać, że opiera się on na tym, że globalny Object
świat nie jest śledzony ani zmieniany.
Konstruktory
Po utworzeniu instancji konstruktor może zwrócić wartość inną niż właśnie utworzona instancja. Ale ta wartość zostanie zignorowana, chyba że jest to obiekt.
Poniższa funkcja wymaga ECMAScript 3, który pozwalał konstruktorom zwracać obiekty niebędące obiektami. Przed ECMAScript 3, który generował błąd, ale try
wtedy nie istniały instrukcje.
function isObject(value) { /* Requires ECMAScript 3 or later */
return new function() { return value; }() === value;
}
Chociaż jest nieco mniej prosty niż w poprzednim przykładzie, ten nie opiera się na żadnej globalnej własności, a zatem może być najbezpieczniejszy.
this
wartość
Stare specyfikacje ECMAScript wymagały, aby this
wartość była obiektem. Wprowadzono ECMAScript 3 Function.prototype.call
, który pozwalał na wywoływanie funkcji o dowolnej this
wartości, ale wymuszanej na obiekcie.
ECMAScript 5 wprowadził tryb ścisły, który usunął to zachowanie, ale w trybie niechlujstwa nadal możemy (ale prawdopodobnie nie powinniśmy) na nim polegać.
function isObject(value) { /* Requires ECMAScript 3 or later in sloppy mode */
return function() { return this === value; }.call(value);
}
[[Prototyp]]
Wszystkie zwykłe obiekty mają wewnętrzny slot o nazwie [[Prototyp]], którego wartość określa, z którego innego obiektu dziedziczy. Wartość może być tylko obiektem lub null
. Dlatego możesz spróbować utworzyć obiekt, który odziedziczy po żądanej wartości, i sprawdź, czy zadziałał.
Zarówno Object.create
i Object.getPrototypeOf
wymagają ECMAScript 5.
function isObject(value) { /* Requires ECMAScript 5 or later */
try {
Object.create(value);
return value !== null;
} catch(err) {
return false;
}
}
function isObject(value) { /* Requires ECMAScript 5 or later */
function Constructor() {}
Constructor.prototype = value;
return Object.getPrototypeOf(new Constructor()) === value;
}
Niektóre nowe sposoby ECMAScript 6
ECMAScript 6 wprowadza pewne nowe pośrednie sposoby sprawdzania, czy wartość jest obiektem. Używają wcześniej widzianego podejścia, aby przekazać wartość do jakiegoś kodu, który wymaga obiektu, owiniętego wewnątrz try
instrukcji w celu wychwycenia błędów. Niektóre ukryte przykłady, nie warte komentowania
Uwaga: Celowo pominąłem niektóre podejścia, takie jak Object.getPrototypeOf(value)
(ES5) i Reflect
metody (ES6), ponieważ wywołują one podstawowe metody wewnętrzne, które mogą robić nieprzyjemne rzeczy, np. Jeśli value
są proxy. Ze względów bezpieczeństwa moje przykłady odnoszą się tylko value
bez bezpośredniego dostępu do nich.
Spróbuj tego
if (objectName instanceof Object == false) {
alert('Not an object');
}
else {
alert('An object');
}
Object.prototype instanceof Object
-> fałsz. Object.create(null) instanceof Object
-> fałsz.
new Date() instanceof Object
=> true
function isObject(o) {
return null != o &&
typeof o === 'object' &&
Object.prototype.toString.call(o) === '[object Object]';
}
function isDerivedObject(o) {
return !isObject(o) &&
null != o &&
(typeof o === 'object' || typeof o === 'function') &&
/^\[object /.test(Object.prototype.toString.call(o));
}
// Loose equality operator (==) is intentionally used to check
// for undefined too
// Also note that, even null is an object, within isDerivedObject
// function we skip that and always return false for null
W JavaScript null
, Object
, Array
, Date
i function
s są wszystkie obiekty. Chociaż null
jest nieco wymyślony. Lepiej więc null
najpierw sprawdzić , czy nie ma wartości zerowej.
Sprawdzanie typeof o === 'object'
gwarancji, które o
są przedmiotem. Bez tej kontroli Object.prototype.toString
byłoby bez znaczenia, ponieważ zwróciłoby obiekt za wszystko, nawet za undefined
i null
! Na przykład: toString(undefined)
zwraca [object Undefined]
!
Po typeof o === 'object'
sprawdzeniu toString.call (o) to świetna metoda sprawdzenia, czy o
jest to obiekt, obiekt pochodny jak Array
, Date
czy function
.
W isDerivedObject
funkcji sprawdza, czy o
jest funkcją. Ponieważ funkcja również jest przedmiotem, dlatego tam jest. Jeśli tego nie zrobił, funkcja zwróci wartość false. Przykład: isDerivedObject(function() {})
powróci false
, ale teraz powróci true
.
Zawsze można zmienić definicję tego, co jest przedmiotem. Zatem można odpowiednio zmienić te funkcje.
function isObject(o) {
return null != o &&
typeof o === 'object' &&
Object.prototype.toString.call(o) === '[object Object]';
}
function isDerivedObject(o) {
return !isObject(o) &&
null != o &&
(typeof o === 'object' || typeof o === 'function') &&
/^\[object /.test(Object.prototype.toString.call(o));
}
// TESTS
// is null an object?
console.log(
'is null an object?', isObject(null)
);
console.log(
'is null a derived object?', isDerivedObject(null)
);
// is 1234 an object?
console.log(
'is 1234 an object?', isObject(1234)
);
console.log(
'is 1234 a derived object?', isDerivedObject(1234)
);
// is new Number(1234) an object?
console.log(
'is new Number(1234) an object?', isObject(new Number(1234))
);
console.log(
'is new Number(1234) a derived object?', isDerivedObject(1234)
);
// is function object an object?
console.log(
'is (new (function (){})) an object?',
isObject((new (function (){})))
);
console.log(
'is (new (function (){})) a derived object?',
isObject((new (function (){})))
);
// is {} an object?
console.log(
'is {} an object?', isObject({})
);
console.log(
'is {} a derived object?', isDerivedObject({})
);
// is Array an object?
console.log(
'is Array an object?',
isObject([])
)
console.log(
'is Array a derived object?',
isDerivedObject([])
)
// is Date an object?
console.log(
'is Date an object?', isObject(new Date())
);
console.log(
'is Date a derived object?', isDerivedObject(new Date())
);
// is function an object?
console.log(
'is function an object?', isObject(function(){})
);
console.log(
'is function a derived object?', isDerivedObject(function(){})
);
Jeśli chcesz sprawdzić, czy prototype
dla object
pochodzi wyłącznie od Object
. Odfiltrowuje String
, Number
, Array
, Arguments
, itd.
function isObject (n) {
return Object.prototype.toString.call(n) === '[object Object]';
}
Lub jako funkcja strzałki z jednym wyrażeniem (ES6 +)
const isObject = n => Object.prototype.toString.call(n) === '[object Object]'
return Object.prototype.toString.call(n) === '[object Object]'
null
czek, ponieważObject.prototype.toString.call(null) === '[object Null]'
var a = [1]
typeof a //"object"
a instanceof Object //true
a instanceof Array //true
var b ={a: 1}
b instanceof Object //true
b instanceof Array //false
var c = null
c instanceof Object //false
c instanceof Array //false
Poproszono mnie o podanie dodatkowych szczegółów. Najbardziej przejrzystym i zrozumiałym sposobem sprawdzenia, czy nasza zmienna jest obiektem, jest typeof myVar
. Zwraca ciąg z rodzaju (np "object"
, "undefined"
).
Niestety albo Array i null również mają typ object
. Aby wziąć tylko prawdziwe przedmioty, należy sprawdzić łańcuch dziedziczenia za pomocą instanceof
operatora. Wyeliminuje to zero, ale tablica ma Object w łańcuchu dziedziczenia.
Tak więc rozwiązaniem jest:
if (myVar instanceof Object && !(myVar instanceof Array)) {
// code for objects
}
/./ instanceof Object //true
Trochę późno ... dla „zwykłych obiektów” (mam na myśli, jak {'x': 5, 'y': 7}) mam ten mały fragment:
function isPlainObject(o) {
return ((o === null) || Array.isArray(o) || typeof o == 'function') ?
false
:(typeof o == 'object');
}
Generuje następny wynik:
console.debug(isPlainObject(isPlainObject)); //function, false
console.debug(isPlainObject({'x': 6, 'y': 16})); //literal object, true
console.debug(isPlainObject(5)); //number, false
console.debug(isPlainObject(undefined)); //undefined, false
console.debug(isPlainObject(null)); //null, false
console.debug(isPlainObject('a')); //string, false
console.debug(isPlainObject([])); //array?, false
console.debug(isPlainObject(true)); //bool, false
console.debug(isPlainObject(false)); //bool, false
To zawsze działa dla mnie. Jeśli zwróci „prawda” tylko wtedy, gdy typem „o” jest „obiekt”, ale nie ma wartości null, tablicy ani funkcji. :)
lodash ma isPlainObject , co może być tym, czego szuka wielu, którzy odwiedzają tę stronę. Zwraca false, gdy podaje funkcję lub tablicę.
_.isObject
które pasuje do tego, co JS uważa za obiekt. Ale zwykle potrzebuję rozróżnić np. Dosłowność obiektu i tablicę, co dokładnie _.isPlainObject
mi pozwala.
To zadziała. Jest to funkcja zwracająca wartość true, false lub ewentualnie null.
const isObject = obj => obj && obj.constructor && obj.constructor === Object;
console.log(isObject({})); // true
console.log(isObject([])); // false
console.log(isObject(new Function)); // false
console.log(isObject(new Number(123))); // false
console.log(isObject(null)); // null
null
wynika z tej odpowiedzi, podczas testów uzyskałem raczej wynik testu końcowego niż false
. Zobacz Kiedy powinienem edytować kod?
Ponieważ wydaje się, że istnieje wiele nieporozumień dotyczących tego, jak poprawnie poradzić sobie z tym problemem, zostawię moje 2 centy (ta odpowiedź jest zgodna ze specyfikacją i daje prawidłowe wyniki we wszystkich okolicznościach):
Testowanie prymitywów:
undefined
null
boolean
string
number
function isPrimitive(o){return typeof o!=='object'||null}
Obiekt nie jest prymitywny:
function isObject(o){return !isPrimitive(o)}
Lub alternatywnie:
function isObject(o){return o instanceof Object}
function isPrimitive(o){return !isObject(o)}
Testowanie dowolnej tablicy:
const isArray=(function(){
const arrayTypes=Object.create(null);
arrayTypes['Array']=true;
arrayTypes['Int8Array']=true;
arrayTypes['Uint8Array']=true;
arrayTypes['Uint8ClampedArray']=true;
arrayTypes['Int16Array']=true;
arrayTypes['Uint16Array']=true;
arrayTypes['Int32Array']=true;
arrayTypes['Uint32Array']=true;
arrayTypes['BigInt64Array']=true;
arrayTypes['BigUint64Array']=true;
arrayTypes['Float32Array']=true;
arrayTypes['Float64Array']=true;
return function(o){
if (!o) return false;
return !isPrimitive(o)&&!!arrayTypes[o.constructor.name];
}
}());
Testowanie obiektu z wyłączeniem: Date
RegExp
Boolean
Number
String
Function
dowolnej tablicy
const isObjectStrict=(function(){
const nativeTypes=Object.create(null);
nativeTypes['Date']=true;
nativeTypes['RegExp']=true;
nativeTypes['Boolean']=true;
nativeTypes['Number']=true;
nativeTypes['String']=true;
nativeTypes['Function']=true;
return function(o){
if (!o) return false;
return !isPrimitive(o)&&!isArray(o)&&!nativeTypes[o.constructor.name];
}
}());
Gdy wszystko inne zawiedzie, używam tego:
var isObject = function(item) {
return item.constructor.name === "Object";
};
item.constructor === Object
?
null
zgłasza wyjątekUncaught TypeError: Cannot read property 'constructor' of null(…)
indexOf
lub z powodu constructor.name
?
The Ramda biblioteka funkcjonalny ma wspaniałą funkcję wykrywania typów JavaScript.
Parafrazując pełną funkcję :
function type(val) {
return val === null ? 'Null' :
val === undefined ? 'Undefined' :
Object.prototype.toString.call(val).slice(8, -1);
}
Musiałem się śmiać, kiedy zdałem sobie sprawę, jak proste i piękne było to rozwiązanie.
Przykładowe użycie z dokumentacji Ramda :
R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"
Po przeczytaniu i wypróbowanie wielu implementacjach, Zauważyłem, że bardzo niewiele osób próbuje sprawdzić dla wartości takich jak JSON
, Math
,document
lub przedmiotów z łańcuchami prototypowych dłużej niż 1 kroku.
Zamiast sprawdzać typeof
naszą zmienną, a następnie hakować przypadki na krawędziach, pomyślałem, że lepiej byłoby, gdyby sprawdzanie było tak proste, jak to możliwe, aby uniknąć konieczności refaktoryzacji, gdy pojawią się nowe operacje podstawowe lub obiekty rodzime, które rejestrują się jakotypeof
obiekt „ „.
W końcu typeof
operator powie ci, czy coś jest obiektem JavaScript , ale definicja obiektu JavaScript jest zbyt szeroka dla większości scenariuszy w świecie rzeczywistym (np typeof null === 'object'
.). Poniżej znajduje się funkcja, która określa, czy zmienna v
jest obiektem, zasadniczo powtarzając dwa sprawdzenia:
v
jest '[object Object]'
. v
zostaje zastąpiony kolejnym prototypem w łańcuchu v = Object.getPrototypeOf(v)
, ale również bezpośrednio poddany ocenie po. Gdy nową wartością v
jest null
, oznacza to, że każdy prototyp, w tym prototyp root (który równie dobrze mógłby być jedynym prototypem w łańcuchu), przeszedł kontrolę w pętli while i możemy zwrócić wartość true. W przeciwnym razie rozpoczyna się nowa iteracja.function isObj (v) {
while ( Object.prototype.toString.call(v) === '[object Object]')
if ((v = Object.getPrototypeOf(v)) === null)
return true
return false
}
console.log('FALSE:')
console.log('[] -> ', isObj([]))
console.log('null -> ', isObj(null))
console.log('document -> ', isObj(document))
console.log('JSON -> ', isObj(JSON))
console.log('function -> ', isObj(function () {}))
console.log('new Date() -> ', isObj(new Date()))
console.log('RegExp -> ', isObj(/./))
console.log('TRUE:')
console.log('{} -> ', isObj({}))
console.log('new Object() -> ', isObj(new Object()))
console.log('new Object(null) -> ', isObj(new Object(null)))
console.log('new Object({}) -> ', isObj(new Object({foo: 'bar'})))
console.log('Object.prototype -> ', isObj(Object.prototype))
console.log('Object.create(null) -> ', isObj(Object.create(null)))
console.log('Object.create({}) -> ', isObj(Object.create({foo: 'bar'})))
console.log('deep inheritance -> ', isObj(Object.create(Object.create({foo: 'bar'}))))
if(typeof value === 'object' && value.constructor === Object)
{
console.log("This is an object");
}
value
jest null
to wygeneruje błąd ...
false
dla obiektu Object.assign({}, {constructor: null})
.
To stare pytanie, ale pomyślałem o pozostawieniu tego tutaj. Większość ludzi sprawdza, czy zmienna {}
oznacza parę klucz-wartość, a nie jaka jest konstrukcja podkreślająca, której JavaScript używa do danej rzeczy, bo szczerze mówiąc, wszystko w JavaScript jest obiektem. Więc odsuwając to na bok. Jeśli zrobisz...
let x = function() {}
typeof x === 'function' //true
x === Object(x) // true
x = []
x === Object(x) // true
// also
x = null
typeof null // 'object'
W większości przypadków chcemy wiedzieć, czy mamy obiekt zasobu z API lub nasze wywołanie bazy danych z ORM. Możemy następnie sprawdzić, czy nie jest Array
, nie null
jest, nie jest typeof 'function'
i jestObject
// To account also for new Date() as @toddmo pointed out
x instanceof Object && x.constructor === Object
x = 'test' // false
x = 3 // false
x = 45.6 // false
x = undefiend // false
x = 'undefiend' // false
x = null // false
x = function(){} // false
x = [1, 2] // false
x = new Date() // false
x = {} // true
true
dlanew Date()
new Date()
znalazłem „nowy” sposób na wykonanie tego rodzaju sprawdzania typu na podstawie tego pytania SO: Dlaczego instanceof zwraca false dla niektórych literałów?
z tego utworzyłem funkcję do sprawdzania typu w następujący sposób:
function isVarTypeOf(_var, _type){
try {
return _var.constructor === _type;
} catch(ex) {
return false; //fallback for null or undefined
}
}
możesz po prostu zrobić:
console.log(isVarTypeOf('asdf', String)); // returns true
console.log(isVarTypeOf(new String('asdf'), String)); // returns true
console.log(isVarTypeOf(123, String)); // returns false
console.log(isVarTypeOf(123, Number)); // returns true
console.log(isVarTypeOf(new Date(), String)); // returns false
console.log(isVarTypeOf(new Date(), Number)); // returns false
console.log(isVarTypeOf(new Date(), Date)); // returns true
console.log(isVarTypeOf([], Object)); // returns false
console.log(isVarTypeOf([], Array)); // returns true
console.log(isVarTypeOf({}, Object)); // returns true
console.log(isVarTypeOf({}, Array)); // returns false
console.log(isVarTypeOf(null, Object)); // returns false
console.log(isVarTypeOf(undefined, Object)); // returns false
console.log(isVarTypeOf(false, Boolean)); // returns true
jest to testowane na Chrome 56, Firefox 52, Microsoft Edge 38, Internet Explorer 11, Opera 43
edytuj:
jeśli chcesz również sprawdzić, czy zmienna jest pusta lub niezdefiniowana, możesz użyć tego zamiast tego:
function isVarTypeOf(_var, _type){
try {
return _var.constructor === _type;
} catch(ex) {
return _var == _type; //null and undefined are considered the same
// or you can use === if you want to differentiate them
}
}
var a = undefined, b = null;
console.log(isVarTypeOf(a, undefined)) // returns true
console.log(isVarTypeOf(b, undefined)) // returns true
console.log(isVarTypeOf(a, null)) // returns true
aktualizacja z komentarza inanc: wyzwanie przyjęte: D
jeśli chcesz stracić porównanie obiektów, możesz spróbować w ten sposób:
function isVarTypeOf(_var, _type, looseCompare){
if (!looseCompare){
try {
return _var.constructor === _type;
} catch(ex){
return _var == _type;
}
} else {
try{
switch(_var.constructor){
case Number:
case Function:
case Boolean:
case Symbol:
case Date:
case String:
case RegExp:
// add all standard objects you want to differentiate here
return _var.constructor === _type;
case Error:
case EvalError:
case RangeError:
case ReferenceError:
case SyntaxError:
case TypeError:
case URIError:
// all errors are considered the same when compared to generic Error
return (_type === Error ? Error : _var.constructor) === _type;
case Array:
case Int8Array:
case Uint8Array:
case Uint8ClampedArray:
case Int16Array:
case Uint16Array:
case Int32Array:
case Uint32Array:
case Float32Array:
case Float64Array:
// all types of array are considered the same when compared to generic Array
return (_type === Array ? Array : _var.constructor) === _type;
case Object:
default:
// the remaining are considered as custom class/object, so treat it as object when compared to generic Object
return (_type === Object ? Object : _var.constructor) === _type;
}
} catch(ex){
return _var == _type; //null and undefined are considered the same
// or you can use === if you want to differentiate them
}
}
}
w ten sposób możesz zrobić podobnie jak komentarz inanc:
isVarTypeOf(new (function Foo(){}), Object); // returns false
isVarTypeOf(new (function Foo(){}), Object, true); // returns true
lub
Foo = function(){};
Bar = function(){};
isVarTypeOf(new Foo(), Object); // returns false
isVarTypeOf(new Foo(), Object, true); // returns true
isVarTypeOf(new Bar(), Foo, true); // returns false
isVarTypeOf(new Bar(), Bar, true); // returns true
isVarTypeOf(new Bar(), Bar); // returns true
instanceof
do sprawdzenia obiektów. Jednak nie jest to nauka ścisła.
new Foo()
zwraca Foo
obiekt, tak samo jak new String()
zwraca String
obiekt lub new Date()
zwraca Date
obiekt, możesz Foo = function(){}; isVarTypeOf(new Foo(), Foo);
również zrobić
null
jest obiektem).