Object.getOwnPropertyNames ve Object.keys


214

Javascript ile Object.getOwnPropertyNamesve Object.keysarasındaki fark nedir ? Ayrıca bazı örnekler takdir edilecektir.


3
Her ikisinde de MDN makalelerine bakılırsa, fark, döndürülen listenin numaralandırılamayan özellikleri içerip içermediğidir: Object.keys()bunları döndürmez, döndürür Object.getOwnPropertyNames().
Sirko

Yanıtlar:


289

Küçük bir fark var. nesnenin tüm kendi özelliklerini Object.getOwnPropertyNames(a)döndürür . tüm numaralandırılabilir kendi özelliklerini döndürür . Bu, nesne özelliklerini bazılarını yapmadan tanımlarsanız, bu iki yöntemin size aynı sonucu vereceği anlamına gelir .aObject.keys(a)enumerable: false

Test etmek kolaydır:

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

Bir özelliği özellik özellikleri tanımlayıcısı (kullanmamanız anlamına gelir) sağlamadan tanımlarsanız Object.defineProperties, örneğin:

a.test = 21;

bu tür özellikler otomatik olarak numaralandırılır ve her iki yöntem de aynı diziyi üretir.


26
Özellikle, lengthdizi nesnelerinin özellikleri numaralandırılamaz, bu nedenle görünmez Object.keys.
Barmar

6
@Barmar lengthNesnelerin özelliği, nesnenin kendisinde değil, prototip üzerindedir, bu nedenle ne listeler ne Object.keysde Object.getOwnPropertyNameslisteler.
Qodesmith

9
@TheQodesmith Object.getOwnPropertyNames(anyArray)içerirlength
thorn̈

6
Ben düzeltilmiş duruyorum! Object.getOwnPropertyNames(anyArray)gerçekten lengthdöndürülen diziye dahil!
Qodesmith

Evet, ama Array.prototype'de de var. Array.prototype'i normal bir dizi gibi değiştirebilmesi biraz garip (yani Array.prototype.push ('her neyse')). Ancak yeni oluşturulan Array örnekleri üzerinde hiçbir etkisi yok gibi görünüyor. stackoverflow.com/questions/48020958/…
trollkotze

21

Diğer bir fark ise dizi Object.getOwnPropertyNamesyönteminin ekstra bir özellik döndürmesi durumundadır length.

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

1

Nesne oluştururken hazır gösterime karşı kurucu. İşte beni yakalayan bir şey.

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

Benim durumumda, fooeğer cat2 tipinde nesneler verirsem fonksiyon çalışmadı.

Nesneleri yaratmanın başka yolları da vardır, böylece orada başka karışıklıklar da olabilir.


Object.getOwnPropertyNamesiçin özellik adlarını dönecektir cat1değil cat2. Nesneyi oluşturmak için iki seçenek arasındaki fark üretmezler Object.getOwnPropertyNamesve Object.keys.
Boric

1
@ Borik Evet haklısın. Object.getPrototypeOf (cat2) sadece cat2 yerine her iki yöntemle kullanmak istedim. Emin olamıyorum çünkü hatırlamıyorum ve kodum yok. Cevabı düzeltirim.
h3dkandi

0

Daha önce açıklandığı gibi, .keysnumaralandırılabilir özellikler döndürmez.

Örneklerle ilgili olarak, tuzak durumlarından biri bir Errornesnedir: bazı özellikleri numaralandırılabilir.
Böylece console.log(Object.keys(new Error('some msg')))verim [], console.log(Object.getOwnPropertyNames(new Error('some msg')))verim["stack", "message"]

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


-5

Başka bir fark (en azından nodejs ile) "getOwnPropertyNames" fonksiyonunun tuşların sırasını garanti etmemesidir, bu yüzden genellikle "keys" fonksiyonunu kullanırım:

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

1
Şu anki Node.js sürümlerinde durum hala geçerli mi ve eğer öyleyse, getOwnPropertyNamesdüzenli olmamaya dair herhangi bir örnek biliyor musunuz ? ES2015 belirten Çünkü siparişiObect.getOwnPropertyNames ederken, siparişObect.keys kadar uygulanmasına hala.
szupie

7
Ben her zaman JS nesne anahtarları sipariş olduğunu düşündüm ve bir uygulama sipariş tutar olsa bile güvenmemelisiniz?
Juan Mendes

1
Bence bu tam tersi; getOwnPropertyNames için sipariş spesifikasyonda tanımlanmıştır. Object.keys uygulamaya bağlıdır.
tjvr

1
: Aşağıdakilerden Tüm belirtilmemiş düzen var for-in loop, Object.keysve Object.getOwnPropertyNames. Bununla birlikte, her üçü de birbirine göre tutarlı bir şekilde numaralandırılacaktır.
Thomas Eding
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.