Object.getOwnPropertyNamesとObject.keys


213

JavaScript Object.getOwnPropertyNamesとの違いは何Object.keysですか?また、いくつかの例をいただければ幸いです。


3
両方のMDN記事から判断すると、違いは、返されるリストに列挙不可能なプロパティが含まれているかどうかです。Object.keys()それらは返されませんが、返されますObject.getOwnPropertyNames()
シルコ2014年

回答:


289

少し違いがあります。オブジェクトのすべての独自のプロパティをObject.getOwnPropertyNames(a)返します。列挙可能なすべての独自のプロパティを返します。つまり、一部を作成せずにオブジェクトのプロパティを定義した場合、これらの2つの方法で同じ結果が得られるということです。aObject.keys(a)enumerable: false

テストは簡単です:

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

たとえば、プロパティ属性記述子を指定せずにプロパティを定義した場合(つまりObject.defineProperties、を使用しない場合)は、次のようになります。

a.test = 21;

その後、そのようなプロパティは自動的に列挙可能になり、両方のメソッドが同じ配列を生成します。


26
特に、length配列オブジェクトのプロパティは列挙できないため、には表示されませんObject.keys
Barmar

6
@Barmar lengthオブジェクトのプロパティはプロトタイプにあり、オブジェクト自体ではないため、リストObject.keysObject.getOwnPropertyNamesリストもしません。
Qodesmith、2017年

9
結果@TheQodesmith Object.getOwnPropertyNames(anyArray)含みlength
ソーン

6
立て直しました!Object.getOwnPropertyNames(anyArray)確かlengthに、返された配列に含まれています!
Qodesmith、2017年

そうです、しかしArray.prototypeにもあります。Array.prototypeを通常の配列(つまり、Array.prototype.push( 'whatever'))のように変更できるのは、奇妙なことです。ただし、新しく作成されたArrayインスタンスには影響がないようです。stackoverflow.com/questions/48020958/…–
trollkotze

21

もう1つの違いは、配列Object.getOwnPropertyNamesメソッドがである追加のプロパティを返す場合ですlength

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

1

オブジェクト作成時のリテラル表記とコンストラクタ。ここに私を獲得したものがあります。

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

したがって、私の場合foo、cat2タイプのオブジェクトを指定した場合、関数は機能しませんでした。

オブジェクトを作成する方法は他にもあるので、そこにも他のねじれがある可能性があります。


Object.getOwnPropertyNamesプロパティ名を返しますcat1し、ではありませんcat2。オブジェクトを作成する2つの方法では、との間に違いはObject.getOwnPropertyNamesありませんObject.keys
Boric

1
@Boricはい、あなたは正しいです。cat2だけでなく、両方のメソッドでObject.getPrototypeOf(cat2)を使用することもできました。覚えていないし、コードがないので、確信が持てません。回答で修正します。
h3dkandi

0

すでに説明したように、.keys列挙可能なプロパティは返しません。

例に関して、落とし穴のケースの1つはErrorオブジェクトです。そのプロパティのいくつかは列挙可能です。
したがって、console.log(Object.keys(new Error('some msg')))利回りは[]console.log(Object.getOwnPropertyNames(new Error('some msg')))利回り["stack", "message"]

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


-5

別の違いは、(少なくともnodejsでは) "getOwnPropertyNames"関数はキーの順序を保証しないことです。そのため、通常は "keys"関数を使用します。

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

1
それは現在のバージョンのNode.jsでも同じです。もしそうであればgetOwnPropertyNames、順序が正しくない例を知っていますか?ES2015はの順序をObect.getOwnPropertyNames指定しているため、の順序Obect.keysはまだ実装次第です。
szupie 2016年

7
私はいつもJSオブジェクトキーの順序はないと思っていました。実装が順序を保持していても、それに依存すべきではありませんか?
Juan Mendes

1
ええと、私はそれが逆だと思います。getOwnPropertyNamesの順序は仕様で定義されています。Object.keysは実装次第です。
tjvr 2017年

1
:以下のすべてが、不特定の順序を持っているfor-in loopObject.keysObject.getOwnPropertyNames。とはいえ、3つすべてが相互に一貫した順序で列挙されます。
Thomas Eding 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.