Object.getOwnPropertyNames vs Object.keys

Jawaban:

289

Ada sedikit perbedaan. Object.getOwnPropertyNames(a)mengembalikan semua properti milik objek a. Object.keys(a)mengembalikan semua properti enumerable sendiri. Ini berarti bahwa jika Anda mendefinisikan properti objek Anda tanpa membuat beberapa dari mereka enumerable: false, kedua metode ini akan memberi Anda hasil yang sama.

Mudah untuk diuji:

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

Jika Anda mendefinisikan properti tanpa memberikan deskriptor atribut properti (artinya Anda tidak menggunakan Object.defineProperties), misalnya:

a.test = 21;

maka properti tersebut menjadi enumerable secara otomatis dan kedua metode menghasilkan array yang sama.

dfsq
sumber
26
Secara khusus, lengthproperti dari objek array tidak dapat dihitung, sehingga tidak muncul di Object.keys.
Barmar
6
@Barmar lengthProperti objek ada pada prototipe, bukan objek itu sendiri, jadi tidak Object.keysjuga tidak Object.getOwnPropertyNamesakan mencantumkannya.
The Qodesmith
9
@TheQodesmith hasil dari Object.getOwnPropertyNames(anyArray)termasuklength
durï
6
Saya berdiri dikoreksi! Object.getOwnPropertyNames(anyArray)memang termasuk lengthdalam array yang dikembalikan!
The Qodesmith
Ya, tapi Array. Prototipe juga memilikinya. Agak aneh bahwa seseorang dapat memodifikasi Array.prototype seperti array normal (yaitu Array.prototype.push ('apa pun')). Tetapi tampaknya tidak berpengaruh pada instance Array yang baru dibuat. stackoverflow.com/questions/48020958/…
trollkotze
21

Perbedaan lainnya adalah dalam hal Object.getOwnPropertyNamesmetode array akan mengembalikan properti tambahan itu length.

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

Notasi literal vs konstruktor saat membuat objek. Inilah sesuatu yang membuat saya.

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

Jadi dalam kasus saya foofungsi tidak berfungsi jika saya memberinya objek dari tipe cat2.

Ada cara lain untuk membuat objek sehingga bisa ada ketegaran lain di sana juga.

h3dkandi
sumber
Object.getOwnPropertyNamesakan mengembalikan nama properti untuk cat1dan tidak cat2. Dua cara membuat objek tidak menghasilkan perbedaan antara Object.getOwnPropertyNamesdan Object.keys.
Boric
1
@Boric Ya Anda benar. Saya bisa bermaksud menggunakan Object.getPrototypeOf (cat2) dengan kedua metode, bukan hanya cat2. Saya tidak yakin karena saya tidak ingat dan tidak memiliki kode. Saya akan memperbaikinya dalam jawaban.
h3dkandi
0

Seperti yang sudah dijelaskan, .keystidak mengembalikan properti enumerable.

Mengenai contoh, salah satu kasus perangkap adalah Errorobjek: beberapa propertinya dapat dihitung.
Jadi sambil console.log(Object.keys(new Error('some msg')))menghasilkan [], console.log(Object.getOwnPropertyNames(new Error('some msg')))menghasilkan["stack", "message"]

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

Shimon S
sumber
-5

Perbedaan lainnya adalah bahwa (setidaknya dengan nodejs) fungsi "getOwnPropertyNames" tidak menjamin urutan kunci, itu sebabnya saya biasanya menggunakan fungsi "kunci":

    Object.keys(o).forEach(function(k) {
      if (!o.propertyIsEnumerable(k)) return;
      // do something...
    });
Olivier Penhoat
sumber
1
Apakah itu masih terjadi dalam versi Node.js saat ini, dan jika demikian, apakah Anda tahu ada contoh getOwnPropertyNamestidak beres? Karena ES2015 menentukan pesanan untukObect.getOwnPropertyNames , sementara pesananObect.keys masih hingga implementasi.
szupie
7
Saya selalu berpikir tidak ada urutan kunci objek JS dan Anda tidak harus bergantung padanya bahkan jika implementasi menjaga urutan?
Juan Mendes
1
Um, saya pikir itu sebaliknya; pesanan untuk getOwnPropertyNames didefinisikan dalam spesifikasi. Objek.kunci terserah implementasi.
tjvr
1
Semua berikut memiliki pesanan yang tidak ditentukan: for-in loop, Object.keys, dan Object.getOwnPropertyNames. Yang mengatakan, ketiganya akan menyebutkan secara konsisten sehubungan satu sama lain.
Thomas Eding