Sprawdź, czy wartość jest obiektem w JavaScript

1362

Jak sprawdzić, czy wartość jest obiektem w JavaScript?

Danny Fox
źródło
4
Zmienna jest zmienną. Może odnosić się do obiektu. Możesz także zdefiniować „obiekt” - jak pokazują odpowiedzi i komentarze, istnieją różne sprzeczne definicje (np. Czy nulljest obiektem).
8
OP, IMO, powinieneś zaakceptować odpowiedź @ Daana, ponieważ jest to najlepsze rozwiązanie i powinno być wymienione powyżej innych odpowiedzi, aby było widoczne jako pierwsze. (Bez obrazy dla innych, którzy również mają dobre odpowiedzi.)
Tiffon,
2
IMHO to naprawdę zależy od tego, co ty (ten, który szuka odpowiedzi na to pytanie) rozważasz Obiekt i dlaczego go sprawdzasz. To pytanie daje różne odpowiedzi, jeśli próbujesz odróżnić tablice (które Przedmiotami) od innych Obiektów lub jeśli próbujesz oddzielić wartości skalarne od „wektorów”. To, czy wartość null ( zgodnie z typof jest Object), czy Funkcje (które Objects) powinny być wykluczone, czy nie, zależy od tego, dlaczego to sprawdzasz. Dlatego jest tak wiele odpowiedzi i większość z nich jest poprawna.
FrancescoMM
const isEmpty = thing => {typeof thing === "obiekt"? ! rzecz || ! Object.keys (rzecz). Długość:! Rzecz && rzecz! == 0};
Mayur S
1
Byłoby wspaniale, gdybyś mógł zacząć od powiedzenia, co dokładnie rozumiesz przez „obiekt”. (Lub, powiedz wprost, że częścią odpowiedzi, której szukasz, jest ustalenie różnych popularnych znaczeń „jest przedmiotem”, a następnie rozróżnienie między nimi.) Brak tego, wszyscy rozmawiają obok siebie.
Don Hatch,

Odpowiedzi:

520

AKTUALIZACJA :

Ta odpowiedź jest niepełna i daje mylące wyniki . Na przykład, w JavaScript nulljest 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.

Michael Krelin - haker
źródło
208
typeofjest operatorem, więc nie ma takiej potrzeby ().
Yoshi
67
Tak nie ma potrzeby Po prostu wolę to w ten sposób.
Michael Krelin - hacker
150
@ MichaelKrelin-hacker: To niefortunne, ponieważ dezorientuje ludzi .
RightSaidFred,
11
@RightSaidFred, nie mam na to wytłumaczenia, ale absolutnie nie jestem skłonny do dodawania dodatkowych nawiasów w tych wyrażeniach :)
Michael Krelin - hacker
117
Ta odpowiedź jest niepoprawna. typeofzwraca „obiekt” dla wartości null, która nie jest obiektem i instanceofnie działa dla obiektów utworzonych przy użyciu Object.create(null).
Nikolai
1631

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.

Głaskanie pod brodę
źródło
31
Funkcje są również obiektami i powinny zostać uwzględnione w czeku.
JS_Riddler,
4
W takim przypadku yourVariable !== nulllepsza praktyka?
hippietrail
9
@RightSaidFred Wydaje się, że 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.
Konstantin Smoljanin
2
@Orion prosta odpowiedź brzmi: tablice są uważane za obiekty. Aby uzyskać bardziej szczegółową odpowiedź, musisz przeczytać dalej, typeofponieważ 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.
Matt Fenwick,
8
@Tresdin Najlepszym sposobem jest bieganie 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]
Jose Rui Santos
537

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
  • wszystko pochodzi od Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){} - funkcje zdefiniowane przez użytkownika
    • C.prototype- własność prototypu funkcji zdefiniowanej przez użytkownika: nie jest toC prototyp
      • new C() - „nowy” - funkcja zdefiniowana przez użytkownika
    • Math
    • Array.prototype
      • tablice
    • {"a": 1, "b": 2} - obiekty utworzone za pomocą notacji dosłownej
    • new Number(3) - owija się wokół prymitywów
    • ... wiele innych rzeczy ...
  • Object.create(null)
  • wszystko pochodzi od 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.getPrototypeOfktó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({})
Matt Fenwick
źródło
22
obj === Object(obj)zwraca truetablice.
Onur Yıldırım
5
var x = []; console.log(x === Object(x)); // return true
Iluminator
6
@ Tablice iluminatora obiektami w JavaScript, jak wspomniałem w mojej odpowiedzi.
Matt Fenwick
1
getPrototypeOfnie działa np. z odwołanymi serwerami proxy, które są obiektami, ale rzucają.
Oriol
2
Dlaczego nie ({}).toString.apply(obj) === '[object Object]'rozróżnia tablic od obiektów, które nie są tablicami
MauricioJuanes
295

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;
};
Daan
źródło
57
W javascript tablica jest także obiektem, więc przez większość czasu chcesz wykluczyć tablicę:return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
Daan
22
dlaczego miałbyś wykluczyć tablicę? Są pełnoprawnymi obiektami.
Nikolai
65
Ponieważ przez większość czasu chcesz odróżnić {} od [] na przykład jako dane wejściowe w funkcji
Daan
5
@Nickolai .. i do iteracji po zagnieżdżonych obiektach.
Ricky Boyce
6
Świetna odpowiedź. Uchwyty nullteż. Powinna być zaakceptowana odpowiedź.
tiffon
179

Object.prototype.toString.call(myVar) wróci:

  • "[object Object]" jeśli myVar jest obiektem
  • "[object Array]" jeśli myVar jest tablicą
  • itp.

Aby uzyskać więcej informacji na ten temat i dlaczego jest to dobra alternatywa dla typeof, sprawdź ten artykuł .

Christophe
źródło
12
Niedawno dowiedziałem się, że typeof [] === 'object'-> true. Właśnie tego potrzebujesz.
Jondlm,
3
@Christophe Nie rozróżnia prymitywów od obiektów . Object.prototype.toString.call(3)-> "[object Number]". Object.prototype.toString.call(new Number(3))-> "[object Number]"
Matt Fenwick,
3
@MattFenwick Nie sądzę, że jest to „obiekt”, który OP próbuje zidentyfikować
Christophe
3
@Christophe, dlaczego tak myślisz? IMHO, przy braku jakiejkolwiek innej definicji podanej przez OP dla „obiektu”, wydaje mi się najbardziej rozsądne, aby przejść do tej, która jest używana konsekwentnie w specyfikacji ECS.
Matt Fenwick,
getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
Pan Polywhirl
115

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
zupa
źródło
isObjectdziała tylko z literałami obiektowymi. Jeśli utworzę niestandardowy typ, utwórz instancję tego typu i przetestuj go, zwracafalse
WickyNilliams
3
@zupa: what !! a does?
4
@ 3000 cóż, jeśli pominiemy część (!! a), to ulega awarii, ponieważ null i undefined nie mają konstruktorów. (!! a) je odfiltrowuje. Czy to jest odpowiedź na Twoje pytanie?
zupa
2
@zupa @ 3000 Boolean(a)jest dłuższy, ale o wiele bardziej intuicyjny. Po prostu nie używaj new Boolean(a): ( oto dlaczego )!
JayVee,
10
Zaskoczony, najlepsza odpowiedź jest tak daleko w dół strony. To w zasadzie odpowiada na pytanie - czy byłoby to reprezentowane w JSON jako coś zaczynającego się od {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.
Kip
81

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 falsezostanie zwrócony. W nullrazie 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

http://devdocs.io/javascript/global_objects/array/isarray

http://devdocs.io/javascript/global_objects/null

2540625
źródło
3
A co z console.log (isObject (new Date ()))? Dlaczego data powinna być obiektem, a nie tablicą?
schirrmacher
5
@macher Ponieważ 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 lengthna 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.
StanE
1
@StanE Tablice są zdecydowanie obiektami. Nie wiadomo, dlaczego myślisz, że obiekty nie mogą mieć lengthwł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.
Oriol
4
@Oriol Ani nie napisałem, że tablice nie są obiektami, ani też nie napisałem, że obiekty nie mogą mieć lengthwłaściwości (miałem na myśli, że literały obiektowe lengthdomyś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.
StanE
2
typeof nulljest "object", nie "undefined".
2540625
80

Z funkcją Array.isArray:

function isObject(o) {
  return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}

Bez funkcji 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, isRegExpitp 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).


isObjectnie będzie działać w przypadku, Object.create(null)ponieważ Object.createwyjaśniono tutaj wewnętrzne wdrożenie , ale można użyć isObjectbardziej 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! 🙂

V. Kovpak
źródło
najlepsza odpowiedź! działa w wielu przypadkach tu
prieston,
Ponieważ zwraca is false dla isObject (myDateObject), nie jest to odpowiedź na pytanie. Nie informuje, czy zmienna jest obiektem, tylko jeśli jest obiektem określonej klasy. Pytanie dotyczy ogólnej funkcji, która zwraca wartość true dla dowolnego obiektu.
Yetanotherjosh
@Yetanotherjosh Jest to rzeczywiście odpowiedź mentioned wspomniałeś o przypadku opisanym w odpowiedzi i chodzi o to, że musisz użyć isDateswojego obiektu DataDbject w celu napisania solidnego kodu, w przeciwnym razie będziesz mieć kruchą isObjectmetodę.
V. Kovpak,
@VladimirKovpak Używanie Datew moim komentarzu zostało źle wybrane, ponieważ tak, odpowiedź dyskutuje Date. Ale Datejest 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.
Yetanotherjosh
@Yetanotherjosh Zaktualizowałem swoją odpowiedź. I dodał jeszcze 1 skrzynkę.
V. Kovpak,
40

O mój Boże! Myślę, że może to być krótsze niż kiedykolwiek, zobaczmy to:

Krótki i końcowy kod

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

Wyjaśnione

Rodzaje zwrotów

nullZwraca typy obiektów JavaScript (w tym )"object"

console.log(typeof null, typeof [], typeof {})

Sprawdzanie ich konstruktorów

Sprawdzanie constructorwł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

Przedstawiamy Function.name

Function.namezwraca 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

Erisan Olasheni
źródło
3
Ten bardzo mi się podoba, krótko i na temat. O ile widzę, zawodzi tylko jedna rzecz. if obj = Object.create(null)i dlaczego miałbyś to zrobić mimo wszystko ...?
Julian Knight
29

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);
Alireza
źródło
Chcesz również sprawdzić, czy to nie jest tablica. więc funkcja isObject (obj) {return obj! == null && typeof obj === 'object' &&! Array.isArray (obj); }
Matt Goo,
Zgadzam się z tobą, ale jak widać w komentarzu, dzieje się tak w angularJs i wspominam o tym w komentarzu przed funkcją, liczą tablicę jako obiekt ... spójrz tutaj, aby uzyskać więcej informacji: docs .angularjs.org / api / ng / function / angular.isObject
Alireza
24

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, undefinedi null), ale powinien wrócić prawdziwe dla wszystkiego innego (w tym Number, Booleanoraz Stringobiektów). Zauważ, że JS nie określa, jakie obiekty „hosta”, takie jak windowlub 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.toStringTagteraz pozwala dostosować dane wyjściowe Object.prototype.toString.call(...), isPlainObjectpowyższa funkcja może falsew 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.

ostatnie dziecko
źródło
Dlaczego typof === „funkcja” jest uważana za obiekt? Funkcja nie jest przedmiotem, prawda? „new myFunc ()” stanie się obiektem, tak, ale zwykłą funkcją?
StanE
Nie, każda funkcja jest obiektem w JavaScript, niezależnie od tego, jak została utworzona. Możesz ustawić na nich właściwości (chyba, że ​​są zamrożone), są to instanceof Objectdwa identyczne literały funkcji nie są ściśle równe, są przekazywane przez odniesienie itp.
ostatnie dziecko
21

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.

kushalvm
źródło
2
Warto zauważyć, że zwraca to również false(zgodnie z życzeniem), gdy anyVarjest funkcją.
Jamie Birch
18

Najbardziej rozsądnym sposobem sprawdzenia rodzaju wartości wydaje się typeofoperator. Jedynym problemem jest to, że jest strasznie zepsuty:

  • Wraca "object"zanull , który należy do typu Null.
  • Powraca "function" obiekty, które można wywołać, które należą do typu Object.
  • Może zwrócić (prawie) wszystko, co chce, w przypadku niestandardowych obiektów, których nie można wywołać. Na przykład IE wydaje się lubić "unknown". Jedynymi niedozwolonymi wynikami są "function"i prymitywne typy.

typeofjest niezawodny tylko w przypadku innych niż nullprymitywne. Zatem sposobem sprawdzenia, czy wartość jest obiektem, byłoby upewnienie się, że zwracany ciąg typeofnie 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 typeofpolecam 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ć

Kompleksowa, ale niewyczerpująca lista prawidłowych metod sprawdzania, czy wartość należy do typu Object.

  • Object konstruktor

    ObjectKonstruktor 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 trywtedy 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 thiswartość była obiektem. Wprowadzono ECMAScript 3 Function.prototype.call, który pozwalał na wywoływanie funkcji o dowolnej thiswartoś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.createi Object.getPrototypeOfwymagają 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 tryinstrukcji 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 Reflectmetody (ES6), ponieważ wywołują one podstawowe metody wewnętrzne, które mogą robić nieprzyjemne rzeczy, np. Jeśli valuesą proxy. Ze względów bezpieczeństwa moje przykłady odnoszą się tylko valuebez bezpośredniego dostępu do nich.

Oriol
źródło
2
„Tylko moja odpowiedź i odpowiedzi Daana są całkowicie poprawne”. jest nieco zarozumiały, biorąc pod uwagę, że całkowicie nie zgadzam się z Twoimi dwoma pierwszymi zdaniami.
zzzzBov
1
@zzzzBov Cóż, przejrzałem wszystkie odpowiedzi i nie zapewniają one zawsze prawidłowej odpowiedzi, z wyjątkiem mojej i Daana. Mogę podać powtarzalne kontrprzykłady większości z nich. Inni zalecają sprawdzenie, czy typeof zwraca „funkcję” czy „obiekt”, ale jak wyjaśniłem, specyfikacja dopuszcza inne wyniki dla niektórych obiektów. Odpowiedź Matta Fenwicka zawiera tę samą poprawną odpowiedź, co odpowiedź Daana, ale także zawiera nieprawidłowe.
Oriol
1
Nie zgodziłem się z założeniem, że twoja odpowiedź jest „całkowicie poprawna”, argumentując, że inni „nie gwarantują, że zawsze odpowiedzą właściwą odpowiedź”, nie podważa w żaden sposób mojego stanowiska. Ponadto pytanie nie zawiera żadnych roszczeń dotyczących tego, jaki wkład powinien generować, jaki wynik.
zzzzBov
1
@zzzzBov Pytanie dotyczy sposobu sprawdzenia, czy coś jest przedmiotem. ECMAScript definiuje, czym jest obiekt, dlatego używam tej definicji. Nie widzę żadnej innej rozsądnej interpretacji. Odpowiedzi, które wykonują inne czynności (np. Wykluczając tablice) mogą być przydatne w niektórych okolicznościach, ale nie sprawdzają, czy coś jest przedmiotem.
Oriol
@Oriol Być może mógłbyś udzielić odpowiedzi na to pytanie. Dlaczego w JavaScript nie ma wbudowanej metody sprawdzania, czy obiekt jest zwykłym obiektem? ?
guest271314,
15

Spróbuj tego

if (objectName instanceof Object == false) {
  alert('Not an object');
}
else {
  alert('An object');
}
Talha
źródło
14
Dlaczego warto sprawdzić booleany?
jkutianski
5
Pomija to dwa przypadki: Object.prototype instanceof Object-> fałsz. Object.create(null) instanceof Object-> fałsz.
Matt Fenwick,
co z datami? new Date() instanceof Object => true
mauron85
13

Gotowe do użycia funkcje sprawdzania

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

Wyjaśnienie

  • W JavaScript null, Object, Array, Datei functions są wszystkie obiekty. Chociaż nulljest nieco wymyślony. Lepiej więc nullnajpierw sprawdzić , czy nie ma wartości zerowej.

  • Sprawdzanie typeof o === 'object'gwarancji, które osą przedmiotem. Bez tej kontroli Object.prototype.toStringbyłoby bez znaczenia, ponieważ zwróciłoby obiekt za wszystko, nawet za undefinedi null! Na przykład: toString(undefined)zwraca [object Undefined]!

    Po typeof o === 'object'sprawdzeniu toString.call (o) to świetna metoda sprawdzenia, czy ojest to obiekt, obiekt pochodny jak Array, Dateczy function.

  • W isDerivedObjectfunkcji sprawdza, czy ojest 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.


Testy

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(){})
);

Inanc Gumus
źródło
13

Jeśli chcesz sprawdzić, czy prototypedla objectpochodzi 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]'
sasi
źródło
1
jest to najlepszy sposób, ale ułatwiłbym to jeszcze w drugiej linii:return Object.prototype.toString.call(n) === '[object Object]'
mesqueeb,
1
Możesz również usunąć nullczek, ponieważObject.prototype.toString.call(null) === '[object Null]'
Gust van de Wal
12
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ą instanceofoperatora. 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
}
Kania
źródło
/./ instanceof Object //true
yckart
11

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. :)

Emilio Grisolía
źródło
Jak wspomniano w poprzednich odpowiedziach, twoje podejście zakończy się niepowodzeniem w przypadku obiektu Date.
Grzegorz Pawlik,
9

lodash ma isPlainObject , co może być tym, czego szuka wielu, którzy odwiedzają tę stronę. Zwraca false, gdy podaje funkcję lub tablicę.

Poklepać
źródło
Doskonały! Wiedziałem, _.isObjectktóre pasuje do tego, co JS uważa za obiekt. Ale zwykle potrzebuję rozróżnić np. Dosłowność obiektu i tablicę, co dokładnie _.isPlainObjectmi pozwala.
limonka
9

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

pizzarob
źródło
2
@SeregPie W przyszłości powinieneś powstrzymać się od edycji kodu w odpowiedziach. Jak nullwynika z tej odpowiedzi, podczas testów uzyskałem raczej wynik testu końcowego niż false. Zobacz Kiedy powinienem edytować kod?
Nick
9

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 Functiondowolnej 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];
    }
}());
c7x43t
źródło
8

Gdy wszystko inne zawiedzie, używam tego:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 
Michał
źródło
1
Dlaczego porównanie ciągów, dlaczego nie po prostu item.constructor === Object?
K3 --- rnc
nullzgłasza wyjątekUncaught TypeError: Cannot read property 'constructor' of null(…)
Vitim.us
@rounce Mam na celu wsparcie starszych wersji IE, dlaczego to nie działa w IE? Z powodu indexOflub z powodu constructor.name?
Jankapunkt
8

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"
DaveGauer
źródło
8

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ć typeofnaszą 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 typeofoperator 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 vjest obiektem, zasadniczo powtarzając dwa sprawdzenia:

  1. Pętla rozpoczyna się, że trwa tak długo, jak stringified wersja vjest '[object Object]'.
    Chciałem, aby wynik funkcji był dokładnie taki, jak w poniższych logach, więc jest to jedyne kryterium „obiektywności”, z jakim się skończyłem. Jeśli zawiedzie, funkcja natychmiast zwraca false.
  2. vzostaje zastąpiony kolejnym prototypem w łańcuchu v = Object.getPrototypeOf(v), ale również bezpośrednio poddany ocenie po. Gdy nową wartością vjest 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'}))))

Gust van de Wal
źródło
6
if(typeof value === 'object' && value.constructor === Object)
{
    console.log("This is an object");
}
Mahak Choudhary
źródło
1
Jeśli valuejest nullto wygeneruje błąd ...
Gerszom
I oczywiście będzie to falsedla obiektu Object.assign({}, {constructor: null}).
user4642212
6

Jeśli wyraźnie chcesz sprawdzić, czy podana wartość to {}.

function isObject (value) {
 return value && typeof value === 'object' && value.constructor === Object;
}
Carlos
źródło
6
const isObject = function(obj) {
  const type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

!!objjest skrótem do sprawdzenia, czy objjest prawdą (do odfiltrowania null)

Ira
źródło
6

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 nulljest, 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
Gilbert
źródło
wyskakuje truedlanew Date()
toddmo
1
@toddmo dzięki za zwrócenie na to uwagi. Teraz przykładowy kod zwraca false dlanew Date()
Gilbert
4

To, co lubię używać, to

function isObject (obj) {
  return typeof(obj) == "object" 
        && !Array.isArray(obj) 
        && obj != null 
        && obj != ""
        && !(obj instanceof String)  }

Myślę, że w większości przypadków Data musi przekazać czek jako Obiekt, więc nie filtruję dat

JohnPan
źródło
4

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
am05mhz
źródło
Nie można wykryć, czy nowa klasa jest obiektem. isVarTypeOf (new (function Foo () {}), Object) // Zwraca false zamiast true. Zobacz moją odpowiedź poniżej, aby sprawdzić poprawność.
Inanc Gumus
Możesz jednak użyć instanceofdo sprawdzenia obiektów. Jednak nie jest to nauka ścisła.
Inanc Gumus
@inanc, cóż, ponieważ new Foo()zwraca Fooobiekt, tak samo jak new String()zwraca Stringobiekt lub new Date()zwraca Dateobiekt, możesz Foo = function(){}; isVarTypeOf(new Foo(), Foo);również zrobić
am05mhz
Tak, tak właśnie mówię: nie sprawdzacie teraz, czy jest to obiekt.
Inanc Gumus
@ inanc Pozdrawiam, szukałem sposobu na sprawdzenie typu (nie tylko obiekt), dostałem się na tę stronę i na drugą stronę, potem byłem zbyt podekscytowany, że zapomniałem kontekstu tego pytania, moje złe :)
am05mhz