2016-05-14 18 views
6

Run nel tuo browser (ES5 +)Perché non riesco a ottenere il conteggio delle proprietà dell'oggetto Navigator in JavaScript?

var propCount = Object.keys(navigator).length; 
console.log(propCount); // 0 

Se lo si fa per un oggetto semplice come quello

let obj = { 
    foo: 'bar', 
    breaking: 'bad' 
} 

let propCount = Object.keys(obj).length; 

console.log(propCount); // 2 

Perché succede?

Ci scusiamo se potrebbe riferirsi ad un altro problema come quando Object.keys(obj) lo sta contando solo per oggetti semplici che non contengano functions/arrays, ma questa è la prima volta che ho incontrato con esso.

E vorrei sapere il motivo.

+0

Sembra che siano proprietà ereditate e 'Object.keys()' fornisce solo proprietà "proprie". '" appName "nel navigatore; // true' ... 'navigator.hasOwnProperty (" appName "); // false' Prova ad usare un semplice ciclo for-in'. –

+0

... e noterei che non sono sicuro che l'oggetto 'navigator' abbia specifiche proprietà enumerabili. In caso contrario, farei attenzione nel fare affidamento su di esso nel codice del mondo reale. –

risposta

6

Object.keys() la funzione restituisce le proprietà dell'oggetto che gli vengono assegnate direttamente.Se fate il seguente:

console.log(navigator.hasOwnProperty('permissions')); // false 

Se volete vedere le proprietà del navigatore effettuare le seguenti operazioni:

for(let i in navigator){ 
    console.log(i); 
} 

elencherà tutte le proprietà dell'oggetto navigator perché per ... in ... il ciclo include il prototipo dell'oggetto.

+0

Attenzione, se 'Object.prototype' viene esteso con una proprietà enumerabile, otterrai proprietà impreviste. Lo stesso con un browser ES3, ma questo è meno di un problema. –

+1

Lo scopo del mio post era mostrare che esiste una differenza tra Object.keys() e ad esempio per ... in loop, che funzionano in modo diverso e Object.keys() assomiglia solo alle proprietà assegnate direttamente. Qualcuno può ovviamente estendere Object.prototype e for ... in loop elencherà anche quella proprietà, ma non era questo il mio punto. – Azamantes

+0

@ AlexanderO'Mara: È vero per qualsiasi proprietà aggiunta, non solo su 'Object.prototype'. L'unico modo per ottenere in modo sicuro tutte le proprietà escludendo quelle specificatamente di 'Object.prototype' sarebbe escluderlo manualmente iniziando con' navigator', ottenendo le sue proprietà usando 'Object.getOwnPropertyNames', e poi usando' Object.getPrototypeOf' in un loop e facendo lo stesso fino a raggiungere 'Object.prototype', poiché non c'è alcuna garanzia di quanti livelli di ereditarietà ci saranno. Ma questo è eccessivo. –

1

Ci sono proprietà enumerabili e non enumerabili in javascript. Object.keys() restituirebbe le proprietà proprie enumerabili di un oggetto. Quindi, nel navigator object, sembra che non ci siano proprietà enumerabili. Quindi Object.keys(navigator) restituisce un array vuoto.

Dal documento,

I Object.keys() restituisce un array di proprie proprietà enumerabili di un determinato oggetto, nello stesso ordine di quella fornita da un per ... in loop.

Se si desidera elencare tutte le proprietà enumerabili enumerabili e non di un certo oggetto, poi si deve scrivere il proprio logica utilizzando Object.getOwnPropertyNames().

Nota: getOwnPropertyNames restituirà entrambe le proprietà enum/non enum di un oggetto.

function getAllProps(obj, props = []){ 
if(Object.getPrototypeOf(obj) == null){ return props; } 
return getAllProps(Object.getPrototypeOf(obj), 
      props.concat(Object.getOwnPropertyNames(obj))); 
} 

console.log(getAllProps(navigator)); 
//This will give you all the properties. 

Se si utilizza for..in ciclo allora che vi darà solo le proprietà enumerabili in tutta la catena di prototipi. E dovrai perdere le proprietà non enumerabili.

+0

@squint Sì, sta facendo perfettamente il suo lavoro. for..in loop esegue iterazioni e raccoglie le proprietà enumerabili finché non soddisfa il prototipo nullo. –

3

Questo perché la maggior parte delle proprietà di navigator sono impostate sul Navigator prototipo, che l'istanza navigator eredita, e Object.keys restituisce solo le proprietà impostate sull'oggetto navigator stesso.

È possibile ottenere queste proprietà dal prototipo con questo:

Object.keys(Object.getPrototypeOf(navigator)); 

Una nota a parte, Firefox ha le seguenti proprietà nell'oggetto navigator stesso:

[ "doNotTrack", "mozPay", "mozContacts", "mozApps" ]