Object.getOwnPropertyNames vs Object.keys


Risposte:


289

C'è una piccola differenza Object.getOwnPropertyNames(a)restituisce tutte le proprietà dell'oggetto a. Object.keys(a)ritorna tutto enumerabile proprietà proprie . Significa che se definisci le proprietà del tuo oggetto senza crearne alcune, enumerable: falsequesti due metodi ti daranno lo stesso risultato.

È facile testare:

var a = {};
Object.defineProperties(a, {
    one: {enumerable: true, value: 'one'},
    two: {enumerable: false, value: 'two'},
});
Object.keys(a); // ["one"]
Object.getOwnPropertyNames(a); // ["one", "two"]

Se si definisce una proprietà senza fornire il descrittore degli attributi di proprietà (nel senso che non si utilizza Object.defineProperties), ad esempio:

a.test = 21;

quindi tale proprietà diventa automaticamente enumerabile ed entrambi i metodi producono lo stesso array.


26
In particolare, le lengthproprietà degli oggetti array non sono enumerabili, quindi non vengono visualizzate in Object.keys.
Barmar

6
@Barmar La lengthproprietà degli oggetti è sul prototipo, non sull'oggetto stesso, quindi né Object.keysObject.getOwnPropertyNameslo elencherà.
The Qodesmith

9
@TheQodesmith il risultato di Object.getOwnPropertyNames(anyArray)includelength
thorn̈

6
Sono corretto! Object.getOwnPropertyNames(anyArray)anzi include lengthnell'array restituito!
The Qodesmith,

Sì, ma ce l'ha anche Array.prototype. È strano che si possa modificare Array.prototype come un normale array (cioè Array.prototype.push ('qualunque' ')). Sembra che non abbia alcun effetto sulle istanze di array appena create. stackoverflow.com/questions/48020958/...
trollkotze

21

Un'altra differenza è nel caso in cui il Object.getOwnPropertyNamesmetodo array restituisca una proprietà aggiuntiva length.

var x = ["a", "b", "c", "d"];
Object.keys(x);  //[ '0', '1', '2', '3' ]
Object.getOwnPropertyNames(x);  //[ '0', '1', '2', '3', 'length' ]

1

Notazione letterale vs costruttore durante la creazione di un oggetto. Ecco qualcosa che mi ha preso.

const cat1 = {
    eat() {},
    sleep() {},
    talk() {}
};

// here the methods will be part of the Cat Prototype
class Cat {
    eat() {}
    sleep() {}
    talk() {}
}

const cat2 = new Cat()

Object.keys(cat1) // ["eat", "sleep", "talk"]
Object.keys(Object.getPrototypeOf(cat2)) // []

Object.getOwnPropertyNames(cat1) // ["eat", "sleep", "talk"]
Object.getOwnPropertyNames(Object.getPrototypeOf(cat2)) // ["eat", "sleep", "talk"]

cat1 // {eat: function, sleep: function, talk: function}
cat2 // Cat {}

// a partial of a function that is used to do some magic redeclaration of props
function foo(Obj) {
    var propNames = Object.keys(Obj);

    // I was missing this if
    // if (propNames.length === 0) {
    //     propNames = Object.getOwnPropertyNames(Obj);
    // }

    for (var prop in propNames) {
        var propName = propNames[prop];

        APIObject[propName] = "reasign/redefine or sth";
    }
}

Quindi nel mio caso il foo funzione non ha funzionato se gli ho dato oggetti di tipo cat2.

Esistono altri modi per creare oggetti in modo che possano esserci anche altri nodi.


Object.getOwnPropertyNamesrestituirà i nomi delle proprietà per cat1e non cat2. I due modi di creare l'oggetto non producono alcuna differenza tra Object.getOwnPropertyNamese Object.keys.
Boric,

1
@Boric Sì, hai ragione. Avrei potuto usare Object.getPrototypeOf (cat2) con entrambi i metodi anziché solo cat2. Non posso esserne sicuro perché non ricordo e non ho il codice. Lo risolverò nella risposta.
h3dkandi,

0

Come già spiegato, .keysnon restituisce proprietà enumerabili.

Per quanto riguarda gli esempi, uno dei casi di trappola è un Erroroggetto: alcune delle sue proprietà sono enumerabili.
Quindi, mentre console.log(Object.keys(new Error('some msg')))cede [], console.log(Object.getOwnPropertyNames(new Error('some msg')))cede["stack", "message"]

console.log(Object.keys(new Error('some msg')));
console.log(Object.getOwnPropertyNames(new Error('some msg')));


-5

Un'altra differenza è che (almeno con nodejs) la funzione "getOwnPropertyNames" non garantisce l'ordine delle chiavi, ecco perché di solito uso la funzione "chiavi":

    Object.keys(o).forEach(function(k) {
      if (!o.propertyIsEnumerable(k)) return;
      // do something...
    });

1
È ancora così nelle versioni attuali di Node.js e, in tal caso, conosci qualche esempio di getOwnPropertyNamesnon essere in ordine? Perché ES2015 specifica un ordine perObect.getOwnPropertyNames , mentre l' ordine perObect.keys è ancora fino all'implementazione.
szupie,

7
Ho sempre pensato che non esistesse un ordine delle chiavi dell'oggetto JS e non dovresti fare affidamento su di essa anche se un'implementazione mantiene l'ordine?
Juan Mendes,

1
Ehm, penso che sia il contrario; l'ordine per getOwnPropertyNames è definito nelle specifiche. Object.keys dipende dall'implementazione.
tjvr,

1
Tutto il seguente ordine ha specificato: for-in loop, Object.keys, e Object.getOwnPropertyNames. Detto questo, tutti e tre verranno elencati in un ordine coerente l'uno rispetto all'altro.
Thomas Eding,
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.