Come verificare se l'oggetto ha delle proprietà in JavaScript?


168

Supponendo che dichiaro

var ad = {}; 

Come posso verificare se questo oggetto conterrà proprietà definite dall'utente?

Risposte:


86

È possibile eseguire il loop delle proprietà dell'oggetto come segue:

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

È importante utilizzare il hasOwnProperty()metodo per determinare se l'oggetto ha la proprietà specificata come proprietà diretta e non ereditata dalla catena di prototipi dell'oggetto.

modificare

Dai commenti: puoi inserire quel codice in una funzione e farlo restituire false non appena raggiunge la parte in cui è presente il commento

Test della prestazione

Test di Object.Keys vs For..In Durante il test di qualsiasi proprietà


2
Ciao Daniel, in realtà sto cercando un dispositivo per verificare se un oggetto contiene proprietà definite dall'utente o meno. Non controllare se esiste una proprietà specifica.
Ricky,

7
@Ricky: puoi inserire quel codice in una funzione e renderlo falso non appena raggiunge la parte in cui è presente il commento.
Daniel Vassallo,

8
Penso che in questi giorni l'utilizzo Object.keyssia il più semplice: var a = [1,2,3];a.something=4;console.log(Object.keys(a))poiché fa già parte di ECMA 5, puoi tranquillamente evitarlo: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
HMR

2
Si noti che "oggigiorno" con ES5, gli oggetti nativi possono avere proprietà proprie non enumerabili, ad es Object.defineProperty(obj, 'foo', {enumerable:false, value:'foo'}).
RobG

2
Questa soluzione è un modo per verificare la presenza di chiavi , ma la risposta vera, efficiente e più corretta è riportata di seguito utilizzando Object.keys (x) .length. Non è necessario creare la propria funzione, ne esiste già una!
Dudewad,

196

È possibile utilizzare il Object.keysmetodo integrato per ottenere un elenco di chiavi su un oggetto e testarne la lunghezza.

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  
}

14
Questo qui è la risposta corretta. La risposta accettata sopra è una soluzione alternativa ed è più costosa della semplice verifica del numero di chiavi; questo ha molto più senso .
Dudewad,

6
Object.keys ( "mystring"); produce anche chiavi che ritengo indesiderabili. Questa risposta è incompleta secondo me.
Mike de Klerk,

2
@MikedeKlerk, per favore, leggilo attentamente, non è Object.keys ("mystring"); è Object.keys (objectVariableName) che restituirà la matrice di tutte le chiavi nell'oggetto. es: {'x': 'abc', 'y': 'def'} sarà ['x', 'y']
Dhaval Chaudhary il

3
@DhavalChaudhary Grazie per la risposta al mio commento. Quando provo questo codicevar str = "MyString"; Object.keys(str); , la console emette 8 tasti, da 0 a 7, per ciascun personaggio. O ancora non capisco la risposta.
Mike de Klerk,

6
@MikedeKlerk ma è solo una soluzione per oggetti non per stringhe, per favore fai riferimento alla domanda.
Dhaval Chaudhary,

111

Che ne dici di fare una semplice funzione?

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

Il hasOwnProperty chiamata del metodo direttamente su Object.prototypeè solo per aggiungere un po 'più di sicurezza , immagina quanto segue usando una obj.hasOwnProperty(...)chiamata normale :

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

Nota: (per il futuro) Il metodo sopra riportato si basa for...insull'istruzione e questa istruzione scorre solo su proprietà enumerabili , nello standard ECMAScript attualmente implementato più ampiamente (3a edizione) il programmatore non ha alcun modo per creare proprietà non enumerabili .

Tuttavia, questo è cambiato ora con ECMAScript 5th Edition e siamo in grado di creare proprietà non enumerabili, non scrivibili o non cancellabili, quindi il metodo sopra può fallire , ad esempio:

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!!

Una soluzione ECMAScript 5 a questo problema sarebbe:

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

Il Object.getOwnPropertyNamesmetodo restituisce un Arraycontenente i nomi di tutti le proprietà di un oggetto, enumerabili o meno , questo metodo è ora implementato dai fornitori di browser, è già su Chrome 5 Beta e l'ultimo WebKit Nightly Builds.

Object.defineProperty è disponibile anche su quei browser e le ultime versioni Alpha di Firefox 3.7.


1
Qual è il vantaggio di Object.prototype.hasOwnProperty.call (obj, prop) rispetto a obj.hasOwnProperty (prop)?
Casey Chu,

3
@Casey, modificato, se un oggetto sovrascrive la hasOwnPropertyproprietà, la funzione potrebbe bloccarsi ... So di essere un po 'paranoico ... ma a volte non sai in quale tipo di ambiente verrà utilizzato il tuo codice, ma sai quale metodo vuoi usare ...
CMS

2
+1 per aver risposto a questa domanda ... e ad altre domande del futuro! :)
Daniel Vassallo,

1
Nota che c'è anche un bug in IE in cui se hai una proprietà con un nome che corrisponde a una proprietà non enumerabile Object.prototype, non viene enumerata da for...in. Quindi isEmptyObject({toString:1})fallirà. Questo è uno dei motivi per cui non si può sfortunati abbastanza utilizzare Objectcome una mappatura general-purpose.
bobince

1
@ MichaelMartin-Smucker: le chiavi restituiscono solo proprietà proprie numerabili , quindi non sono adatte qui.
RobG

58

Con jQuery puoi usare:

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

A partire da jQuery 1.4 questo metodo controlla sia le proprietà sull'oggetto stesso sia le proprietà ereditate dai prototipi (in quanto non utilizza hasOwnProperty).

Con ECMAScript 5th Edition nei browser moderni (IE9 +, FF4 +, Chrome5 +, Opera12 +, Safari5 +) puoi utilizzare il metodo Object.keys integrato :

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

O semplicemente vecchio JavaScript:

var isEmpty = function(obj) {
               for(var p in obj){
                  return false;
               }
               return true;
            };



11

Se si desidera utilizzare lodash , è possibile utilizzare il somemetodo.

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

Vedi questo piccolo esempio di jsbin


var x = [1,2] // true
djv il

@damionjn Ho aggiunto il tuo codice all'esempio. Vedo il tuo punto con l'array che restituisce la risposta sbagliata, ma OP inizialmente ha dichiarato una variabile come oggetto, quindi credo che vada bene assumerlo. C'è una risposta sopra che utilizza il metodo isEmpty di sottolineatura (lodash ha lo stesso metodo). Questa risposta ha lo stesso identico problema. Se si dà a isEmpty un array non vuoto, si otterrà anche un risultato errato.
sfs

Abbastanza giusto, ma dovremmo fornire risposte con tutte le basi coperte per essere sicuri delle migliori pratiche. Hai ragione, ho superato la sua risposta senza alcuna critica. Solo per chiunque passi, questo non è un metodo dedicato agli oggetti. _.some([1, 2]) // true Assicurati di controllare prima: stackoverflow.com/a/13356338/1922747
djv

5
for (var hasProperties in ad) break;
if (hasProperties)
    ... // ad has properties

Se devi essere sicuro e verificare la presenza di prototipi di oggetti (questi vengono aggiunti da determinate librerie e non presenti per impostazione predefinita):

var hasProperties = false;
for (var x in ad) {
    if (ad.hasOwnProperty(x)) {
        hasProperties = true;
        break;
    }
}
if (hasProperties)
    ... // ad has properties

1
nella tua soluzione non esiste alcun filtro per le proprietà indesiderate del prototipo, ciò significa che potrebbe comportarsi in modo errato quando si utilizza una libreria come Prototype.js o un utente inesperto ha aggiunto proprietà prototipo aggiuntive all'oggetto. Dai un'occhiata alla soluzione Daniels su questa pagina.
Joscha,

Non è necessario utilizzare una libreria o essere inesperti per estendere il prototipo di un oggetto. Alcuni programmatori esperti lo fanno sempre.
Alsciende,

2
for(var memberName in ad)
{
  //Member Name: memberName
  //Member Value: ad[memberName]
}

Membro significa proprietà Membro, variabile membro, come si desidera chiamarla> _>

Il codice sopra restituirà TUTTO, incluso toString ... Se vuoi solo vedere se il prototipo dell'oggetto è stato esteso:

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

}

Nota A: controlliamo se il membro dell'oggetto fittizio ha lo stesso tipo del membro dell'oggetto di test. Se si tratta di un'estensione, il tipo di membro dummyobject deve essere "non definito"


Ciao, posso solo sapere se un oggetto contiene proprietà o no? Grazie
Ricky,

nella tua soluzione non esiste alcun filtro per le proprietà indesiderate del prototipo, ciò significa che potrebbe comportarsi in modo errato quando si utilizza una libreria come Prototype.js o un utente inesperto ha aggiunto proprietà prototipo aggiuntive all'oggetto.
Joscha,

controlla la soluzione Daniels in questa pagina - è meno soggetta ad errori!
Joscha,

2
Il tuo primo blocco di codice non lo copre affatto. il secondo blocco di codice si comporta male se aggiungo una variabile all'oggetto "ad" che non è definito. Davvero, controlla la risposta di Daniels, è l'unica corretta e veloce, poiché utilizza un'implementazione nativa chiamata "hasOwnProperty".
Joscha,

@Ricky: se vuoi verificare se un oggetto contiene proprietà, puoi semplicemente usare l'esempio nella mia risposta: stackoverflow.com/questions/2673121/… . Se il codice raggiunge il commento, il tuo oggetto non avrebbe proprietà dirette. In caso contrario, lo farebbe.
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

Semplice, funziona in tutti i browser e anche se tecnicamente è un ciclo per tutte le chiavi dell'oggetto NON passa in ciclo tutti ... o c'è 0 e il ciclo non viene eseguito o ce n'è uno e si interrompe dopo il primo uno (perché tutto ciò che stiamo controllando è se c'è QUALSIASI ... quindi perché continuare?)


1

Risposta molto tardi, ma è così che potresti gestirla con i prototipi.

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

Object.prototype.IsAny = function() {
    return Object.keys(this).Any();
}

0

Quando si è certi che l'oggetto sia definito dall'utente, il modo più semplice per determinare se UDO è vuoto sarebbe il seguente codice:

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

Anche se questo metodo è (per natura) deduttivo, è il più veloce e il più veloce possibile.

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

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

ps:! non usarlo su oggetti definiti dal browser.


... restituisce 0; ritorno 1}; sarebbe lo stesso?
commonpike,

1
@pike no, return! 1; return! 0 equivale a return false; return true
Christophe

0

Risposta tardiva, ma alcuni framework gestiscono gli oggetti come enumerabili. Pertanto, bob.js può farlo in questo modo:

var objToTest = {};
var propertyCount = bob.collections.extend(objToTest).count();

0

È possibile utilizzare quanto segue:

Doppio botto !! ricerca di proprietà

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

hasOwnProperty Questo è qualcosa che ho usato per usare:

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

Tuttavia, JavaScript ha deciso di non proteggere il nome del metodo, quindi potrebbe essere manomesso.

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

prop in myObject

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

tipo di

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

Tuttavia, non controlla null.

Penso che questo sia il modo migliore.

in operatore

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");
}

risultato:

Il nome esiste in myObject

Ecco un collegamento che approfondisce l'operatore in: Determinare se esiste una proprietà oggetto


0

Funzione 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

Esempi:


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

-1

Cosa ne pensi di questo?

var obj = {},
var isEmpty = !obj;
var hasContent = !!obj

Questa risposta non risponde alla domanda. OP chiede se un oggetto contiene proprietà definite dall'utente - la tua risposta verifica se l'oggetto stesso verrà convertito in un valore booleano falso.
Jasmonate,

... e ho anche capito in seguito che James aveva già incluso questa opzione nella sua risposta. Scusate ragazzi.
Peter Toth,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.