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 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.
typeofjest operatorem, więc nie ma takiej potrzeby ().
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).
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 !== nulllepsza 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.
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.
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'truenullundefinedCo to jest obiekt (tzn. Nie prymityw)?
Object.prototypeObject.prototype
Function.prototype
ObjectFunctionfunction 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żytkownikaMathArray.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.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({})
obj === Object(obj)zwraca truetablice.
var x = []; console.log(x === Object(x)); // return true
getPrototypeOfnie 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]'
nullteż. 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
isObjectdział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 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
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.
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.
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.
typeof nulljest "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, 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! 🙂
isDateswojego obiektu DataDbject w celu napisania solidnego kodu, w przeciwnym razie będziesz mieć kruchą isObjectmetodę.
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.
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
nullZwraca typy obiektów JavaScript (w tym )"object"
console.log(typeof null, typeof [], typeof {})
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
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
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, 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.
instanceof Objectdwa 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 anyVarjest funkcją.
Najbardziej rozsądnym sposobem sprawdzenia rodzaju wartości wydaje się typeofoperator. 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.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ć
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.
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, 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.
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 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]'
return Object.prototype.toString.call(n) === '[object Object]'
nullczek, 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ą 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
}
/./ 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ę.
_.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.
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
nullwynika 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 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];
}
}());
Gdy wszystko inne zawiedzie, używam tego:
var isObject = function(item) {
return item.constructor.name === "Object";
};
item.constructor === Object?
nullzgłasza wyjątekUncaught TypeError: Cannot read property 'constructor' of null(…)
indexOflub 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ć 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:
vjest '[object Object]'. 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'}))))
if(typeof value === 'object' && value.constructor === Object)
{
console.log("This is an object");
}
valuejest nullto wygeneruje błąd ...
falsedla 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 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
truedlanew 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
instanceofdo sprawdzenia obiektów. Jednak nie jest to nauka ścisła.
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ć
nulljest obiektem).