Jak sprawdzić, czy obiekt ma jakieś właściwości w JavaScript?

167

Zakładając, że deklaruję

var ad = {}; 

Jak mogę sprawdzić, czy ten obiekt będzie zawierał właściwości zdefiniowane przez użytkownika?

Ricky
źródło

Odpowiedzi:

86

Możesz przeglądać właściwości obiektu w następujący sposób:

for(var prop in ad) {
    if (ad.hasOwnProperty(prop)) {
        // handle prop as required
    }
}

Ważne jest, aby użyć tej hasOwnProperty()metody, aby określić, czy obiekt ma określoną właściwość jako właściwość bezpośrednią, a nie jest dziedziczony z łańcucha prototypów obiektu.

Edytować

Z komentarzy: Możesz umieścić ten kod w funkcji i sprawić, by zwracał fałsz, gdy tylko dotrze do części, w której znajduje się komentarz

Test wydajności

Test Of Object.Keys vs For..In Podczas testowania dowolnych właściwości

Daniel Vassallo
źródło
2
Cześć Daniel, właściwie szukam urządzenia do sprawdzenia, czy obiekt zawiera właściwości zdefiniowane przez użytkownika, czy nie. Nie sprawdzać, czy istnieje określona nieruchomość.
Ricky
7
@Ricky: Możesz umieścić ten kod w funkcji i sprawić, by zwracał fałsz, gdy tylko dotrze do części, w której jest komentarz.
Daniel Vassallo,
8
Myślę, że w dzisiejszych czasach używanie Object.keysbyłoby najłatwiejsze: var a = [1,2,3];a.something=4;console.log(Object.keys(a))ponieważ jest już częścią ECMA 5, możesz go bezpiecznie dopasować: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ ...
HMR
2
Zwróć uwagę, że „obecnie” w ES5 obiekty natywne mogą mieć niewyliczalne własne właściwości, np Object.defineProperty(obj, 'foo', {enumerable:false, value:'foo'}).
RobG
2
To rozwiązanie jest sposobem na sprawdzenie istniejących kluczy , ale prawdziwa, wydajna i najbardziej poprawna odpowiedź znajduje się poniżej przy użyciu Object.keys (x) .length. Nie musisz tworzyć własnej funkcji, taka już istnieje!
dudewad
193

Możesz użyć wbudowanej Object.keysmetody, aby uzyskać listę kluczy obiektu i przetestować jego długość.

var x = {};
// some code where value of x changes and than you want to check whether it is null or some object with values

if(Object.keys(x).length > 0){
 // Your code here if x has some properties  
}
Dhaval Chaudhary
źródło
13
Tutaj jest poprawna odpowiedź. Zaakceptowana powyżej odpowiedź jest obejściem i jest droższa niż zwykłe sprawdzenie liczby kluczy; to ma większy sens .
dudewad
6
Object.keys ("mystring"); daje również klucze, co moim zdaniem jest niepożądane. Moim zdaniem ta odpowiedź jest niepełna.
Mike de Klerk
2
@MikedeKlerk, przeczytaj uważnie, to nie jest Object.keys ("mystring"); to Object.keys (objectVariableName), która zwróci tablicę wszystkich kluczy w obiekcie. ex: {'x': 'abc', 'y': 'def'} to będzie ['x', 'y']
Dhaval Chaudhary
3
@DhavalChaudhary Dzięki za odpowiedź na mój komentarz. Kiedy próbuję tego kodu var str = "MyString"; Object.keys(str);, konsola wyświetla 8 kluczy, od 0 do 7, dla każdego znaku. Czy nadal nie rozumiem odpowiedzi.
Mike de Klerk
6
@MikedeKlerk, ale jest to jedyne rozwiązanie dla obiektów, a nie dla ciągów znaków.
Dhaval Chaudhary
111

A co z prostą funkcją?

function isEmptyObject(obj) {
  for(var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
      return false;
    }
  }
  return true;
}

isEmptyObject({}); // true
isEmptyObject({foo:'bar'});  // false

hasOwnPropertyWywołanie metody bezpośrednio po Object.prototypeto tylko, aby dodać trochę więcej bezpieczeństwa , wyobraź sobie następujące używając normalnego obj.hasOwnProperty(...)połączenia:

isEmptyObject({hasOwnProperty:'boom'});  // false

Uwaga: (na przyszłość) Powyższa metoda opiera się na for...ininstrukcji, a ta instrukcja iteruje tylko po wyliczalnych właściwościach, w obecnie najszerzej zaimplementowanym standardzie ECMAScript (3. edycja) programista nie ma możliwości tworzenia niewliczalnych właściwości .

Jednak zmieniło się to teraz wraz z ECMAScript 5th Edition i jesteśmy w stanie tworzyć niewliczalne, niezapisywalne lub nieusuwalne właściwości, więc powyższa metoda może zawieść , np .:

var obj = {};
Object.defineProperty(obj, 'test', { value: 'testVal', 
  enumerable: false,
  writable: true,
  configurable: true
});
isEmptyObject(obj); // true, wrong!!
obj.hasOwnProperty('test'); // true, the property exist!!

Rozwiązaniem tego problemu w ECMAScript 5 byłoby:

function isEmptyObject(obj) {
  return Object.getOwnPropertyNames(obj).length === 0;
}

Że Object.getOwnPropertyNamesmetoda zwraca Arrayzawierający nazwy wszystkich tych własnych właściwości obiektu, przeliczalnego czy nie , metoda ta jest realizowana obecnie przez producentów przeglądarek, to już na Chrome 5 Beta oraz najnowszy WebKit Nightly buduje.

Object.defineProperty jest również dostępny w tych przeglądarkach i najnowszych wydaniach Firefoksa 3.7 Alpha.

CMS
źródło
1
Jaka jest przewaga Object.prototype.hasOwnProperty.call (obj, prop) nad obj.hasOwnProperty (prop)?
Casey Chu
3
@ Casey, edytowane, jeśli obiekt nadpisuje hasOwnPropertywłaściwość, funkcja może się zawiesić ... Wiem, że jestem trochę paranoikiem ... ale czasami nie wiesz, w jakim środowisku twój kod będzie używany, ale wiesz, jakiej metody chcesz użyć ...
CMS
2
+1 za odpowiedź na to pytanie ... i inne pytania dotyczące przyszłości! :)
Daniel Vassallo
1
Zauważ, że w IE występuje również błąd polegający na tym, że jeśli masz właściwość o nazwie, która pasuje do niewliczalnej właściwości w Object.prototype, nie jest ona wyliczana przez for...in. Więc isEmptyObject({toString:1})zawiedzie. Jest to jeden z nieszczęsnych powodów nie można całkiem używają Objectjako odwzorowanie ogólnego przeznaczenia.
bobince
1
@ MichaelMartin-Smucker - klucze zwracają tylko wyliczalne własne właściwości, więc nie są tutaj odpowiednie.
RobG
58

Dzięki jQuery możesz użyć:

$.isEmptyObject(obj); // Returns: Boolean

Od jQuery 1.4 ta metoda sprawdza zarówno właściwości samego obiektu, jak i właściwości odziedziczone po prototypach (w tym sensie, że nie używa hasOwnProperty).

Z ECMAScript 5th Edition w nowoczesnych przeglądarkach (IE9 +, FF4 +, Chrome5 +, Opera12 +, Safari5 +) możesz skorzystać z wbudowanej metody Object.keys :

var obj = { blah: 1 };
var isEmpty = !Object.keys(obj).length;

Lub zwykły stary JavaScript:

var isEmpty = function(obj) {
               for(var p in obj){
                  return false;
               }
               return true;
            };
kayz1
źródło
13

Jeśli używasz underscore.js, możesz użyć funkcji _.isEmpty :

var obj = {};
var emptyObject = _.isEmpty(obj);
Gruff Bunny
źródło
1
Nie jest to metoda dedykowana przedmiotom tylko dla przechodniów. _.isEmpty([]) // true
Koniecznie
11

Jeśli chcesz użyć lodash , możesz użyć tej somemetody.

_.some(obj) // returns true or false

Zobacz ten mały przykład jsbin

sfs
źródło
var x = [1,2] // true
djv
@damionjn Dodałem Twój kod do przykładu. Widzę twój punkt widzenia z tablicą zwracającą złą odpowiedź, ale OP początkowo zadeklarował zmienną jako obiekt, więc uważam, że można to założyć. Powyżej znajduje się odpowiedź wykorzystująca podkreślenia isEmpty (ta sama metoda ma lodash). Ta odpowiedź dotyczy dokładnie tego samego problemu. Jeśli podasz isEmpty niepustą tablicę, otrzymasz również zły wynik.
sfs
W porządku, ale powinniśmy udzielić odpowiedzi z uwzględnieniem wszystkich podstaw, aby mieć pewność co do najlepszych praktyk. Masz rację, przeszedłem przez jego odpowiedź bez żadnej krytyki. Nie jest to metoda dedykowana przedmiotom tylko dla przechodniów. _.some([1, 2]) // true
Koniecznie
5
for (var hasProperties in ad) break;
if (hasProperties)
    ... // ad has properties

Jeśli musisz być bezpieczny i poszukać prototypów Object (są one dodawane przez niektóre biblioteki, a nie są tam domyślnie):

var hasProperties = false;
for (var x in ad) {
    if (ad.hasOwnProperty(x)) {
        hasProperties = true;
        break;
    }
}
if (hasProperties)
    ... // ad has properties
Casey Chu
źródło
1
w twoim rozwiązaniu nie ma filtrowania pod kątem niepożądanych właściwości prototypu, co oznacza, że ​​może działać niepoprawnie, gdy używasz biblioteki takiej jak Prototype.js lub niedoświadczony użytkownik dodał dodatkowe właściwości prototypu do obiektu. Sprawdź rozwiązanie Daniels na tej stronie.
Joscha
Nie musisz używać biblioteki ani być niedoświadczonym, aby rozszerzyć prototyp obiektu. Niektórzy doświadczeni programiści robią to cały czas.
Alsciende
2
for(var memberName in ad)
{
  //Member Name: memberName
  //Member Value: ad[memberName]
}

Składnik oznacza właściwość członka, zmienną składową, jakkolwiek chcesz to nazwać> _>

Powyższy kod zwróci WSZYSTKO, w tym toString ... Jeśli chcesz tylko sprawdzić, czy prototyp obiektu został rozszerzony:

var dummyObj = {};  
for(var memberName in ad)
{
  if(typeof(dummyObj[memberName]) == typeof(ad[memberName])) continue; //note A
  //Member Name: memberName
  //Member Value: ad[memberName]

}

Uwaga A: Sprawdzamy, czy element członkowski obiektu zastępczego ma ten sam typ, co element członkowski obiektu testowego. Jeśli jest to rozszerzenie, typ składowy obiektu dummyobject powinien być „niezdefiniowany”

Warty
źródło
Cześć, czy mogę po prostu wiedzieć, czy obiekt zawiera właściwości, czy nie? Dzięki
Ricky
w twoim rozwiązaniu nie ma filtrowania pod kątem niepożądanych właściwości prototypu, co oznacza, że ​​może działać niepoprawnie, gdy używasz biblioteki takiej jak Prototype.js lub niedoświadczony użytkownik dodał dodatkowe właściwości prototypu do obiektu.
Joscha
sprawdź rozwiązanie Daniels na tej stronie - jest mniej podatne na błędy!
Joscha
2
Twój pierwszy blok kodu w ogóle go nie obejmuje. drugi blok kodu zachowuje się nieprawidłowo, jeśli dodam zmienną do obiektu „ad”, która jest niezdefiniowana. Naprawdę, sprawdź odpowiedź Danielsa, jedyna poprawna i szybka, ponieważ używa natywnej implementacji o nazwie „hasOwnProperty”.
Joscha
@Ricky: Jeśli chcesz sprawdzić, czy obiekt zawiera właściwości, możesz po prostu użyć przykładu w mojej odpowiedzi: stackoverflow.com/questions/2673121/… . Jeśli kod dotrze do komentarza, Twój obiekt nie będzie miał żadnych bezpośrednich właściwości. Jeśli nie, to tak.
Daniel Vassallo
2
var hasAnyProps = false; for (var key in obj) { hasAnyProps = true; break; }
// as of this line hasAnyProps will show Boolean whether or not any iterable props exist

Proste, działa w każdej przeglądarce i chociaż technicznie jest to pętla dla wszystkich kluczy w obiekcie, NIE przechodzi przez nie wszystkie ... albo jest 0 i pętla nie działa, albo jest kilka i zrywa się po pierwszym jeden (ponieważ sprawdzamy tylko, czy jest JAKIEKOLWIEK ... więc po co kontynuować?)

Jimbo Jonny
źródło
1

Bardzo późna odpowiedź, ale tak można sobie z tym poradzić w przypadku prototypów.

Array.prototype.Any = function(func) {
    return this.some(func || function(x) { return x });
}

Object.prototype.IsAny = function() {
    return Object.keys(this).Any();
}
Zysk
źródło
0

Gdy upewnisz się, że obiekt jest obiektem zdefiniowanym przez użytkownika, najłatwiejszym sposobem określenia, czy UDO jest pusty, będzie następujący kod:

isEmpty=
/*b.b Troy III p.a.e*/
function(x,p){for(p in x)return!1;return!0};

Chociaż ta metoda jest (z natury) dedukcyjna, - jest najszybsza i najszybsza z możliwych.

a={};
isEmpty(a) >> true

a.b=1
isEmpty(a) >> false 

ps:! nie używaj go na obiektach zdefiniowanych w przeglądarce.

Bill the Lizard
źródło
... return 0; return 1}; byłby taki sam?
Commonpike
1
@pike no, return! 1; return! 0 oznacza to samo, co return false; return true
Christophe
0

Późna odpowiedź, ale niektóre struktury traktują obiekty jako wyliczalne. Dlatego bob.js może to zrobić w następujący sposób:

var objToTest = {};
var propertyCount = bob.collections.extend(objToTest).count();
Tengiz
źródło
0

Możesz użyć następujących:

Podwójny huk !! wyszukiwanie właściwości

var a = !![]; // true
var a = !!null; // false

hasOwnProperty To jest coś, czego używałem:

var myObject = {
  name: 'John',
  address: null
};
if (myObject.hasOwnProperty('address')) { // true
  // do something if it exists.
}

Jednak JavaScript zdecydował się nie chronić nazwy metody, więc można było przy niej manipulować.

var myObject = {
  hasOwnProperty: 'I will populate it myself!'
};

prop w myObject

var myObject = {
  name: 'John',
  address: null,
  developer: false
};
'developer' in myObject; // true, remember it's looking for exists, not value.

typ

if (typeof myObject.name !== 'undefined') {
  // do something
}

Jednak nie sprawdza null.

Myślę, że to najlepszy sposób.

w operatorze

var myObject = {
  name: 'John',
  address: null
};

if('name' in myObject) {
  console.log("Name exists in myObject");
}else{
  console.log("Name does not exist in myObject");
}

wynik:

Nazwa istnieje w myObject

Oto link, który prowadzi do bardziej szczegółowych informacji na temat operatora in: Określanie, czy właściwość obiektu istnieje

Jamesa Drinkarda
źródło
0

Funkcja ES6

/**
 * Returns true if an object is empty.
 * @param  {*} obj the object to test
 * @return {boolean} returns true if object is empty, otherwise returns false
 */
const pureObjectIsEmpty = obj => obj && obj.constructor === Object && Object.keys(obj).length === 0

Przykłady:


let obj = "this is an object with String constructor"
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = {}
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = []
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = [{prop:"value"}]
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = {prop:"value"}
console.log(pureObjectIsEmpty(obj)) // empty? false
Sébastien
źródło
-1

Co powiesz na to?

var obj = {},
var isEmpty = !obj;
var hasContent = !!obj
Peter Toth
źródło
Ta odpowiedź nie odpowiada na pytanie. OP pyta, czy obiekt zawiera właściwości zdefiniowane przez użytkownika - Twoja odpowiedź sprawdza, czy sam obiekt zostanie przekonwertowany na wartość logiczną fałsz.
Jasmonate
... a później zdałem sobie sprawę, że James zawarł już tę opcję w swojej odpowiedzi. Przepraszam chłopaki.
Peter Toth