250

What's the difference between Object.getOwnPropertyNames and Object.keys in javascript? Also some examples would be appreciated.

kamilkp
  • 8,920
  • 6
  • 31
  • 55
  • 3
    Judging from MDN articles on both, the difference is, whether the returned list includes the non-enumerable properties: [`Object.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) does not return them, while [`Object.getOwnPropertyNames()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames) does. – Sirko Mar 26 '14 at 10:46
  • 5
    [MDN: Enumerability and ownership of properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties) – Bergi Feb 25 '15 at 00:35

5 Answers5

322

There is a little difference. Object.getOwnPropertyNames(a) returns all own properties of the object a. Object.keys(a) returns all enumerable own properties. It means that if you define your object properties without making some of them enumerable: false these two methods will give you the same result.

It's easy to test:

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

If you define a property without providing property attributes descriptor (meaning you don't use Object.defineProperties), for example:

a.test = 21;

then such property becomes an enumerable automatically and both methods produce the same array.

Scott Enock
  • 61
  • 10
dfsq
  • 182,609
  • 24
  • 222
  • 242
  • 32
    In particular, the `length` properties of array objects is not enumerable, so it doesn't show up in `Object.keys`. – Barmar Apr 01 '16 at 02:04
  • 8
    @Barmar The `length` property of objects is on the prototype, not the object itself, so neither `Object.keys` nor `Object.getOwnPropertyNames` will list it. – The Qodesmith Jun 14 '17 at 22:04
  • 11
    @TheQodesmith the result of `Object.getOwnPropertyNames(anyArray)` includes `length` – thorn0 Oct 25 '17 at 11:11
  • 7
    I stand corrected! `Object.getOwnPropertyNames(anyArray)` indeed does include `length` in the returned array! – The Qodesmith Oct 25 '17 at 16:35
  • Yeah, but Array.prototype has it, too. It's kind of weird that one can modify Array.prototype like a normal array (i.e. Array.prototype.push('whatever')). But it seems to have no effect on newly created Array instances. https://stackoverflow.com/questions/48020958/why-is-length-a-property-of-array-not-array-prototype-chain – trollkotze May 27 '18 at 07:59
  • DIY `length` property is not enumerable: `Object.getOwnPropertyDescriptor([], 'length')` – zurfyx Oct 13 '18 at 11:11
26

Another difference is in case of array Object.getOwnPropertyNames method will return an extra property that is length.

var x = ["a", "b", "c", "d"];
Object.keys(x);  //[ '0', '1', '2', '3' ]
Object.getOwnPropertyNames(x);  //[ '0', '1', '2', '3', 'length' ]
Praveen Soni
  • 675
  • 6
  • 20
manas
  • 4,872
  • 7
  • 39
  • 50
4

Literal notation vs constructor when creating object. Here is something that got me.

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

So in my case the foo function didn't work if I gave it objects of the cat2 type.

There are other ways to create objects so there could be other kinks in there as well.

h3dkandi
  • 772
  • 6
  • 25
  • `Object.getOwnPropertyNames` will return the property names for `cat1` and not `cat2`. The two ways of creating the object do not produce a difference between `Object.getOwnPropertyNames` and `Object.keys`. – Boric Sep 19 '19 at 19:09
  • 1
    @Boric Yes you are correct. I could have meant to use Object.getPrototypeOf(cat2) with both methods instead of just cat2. I can't be for sure because I don't remember and don't have the code. I will fix it in the answer. – h3dkandi Sep 20 '19 at 06:38
0

As was already explained, .keys doesn't return non-enumerable properties.

Regarding to examples, one of pitfall cases is an Error object: some of its properties are non-enumerable.
So while console.log(Object.keys(new Error('some msg'))) yields [], console.log(Object.getOwnPropertyNames(new Error('some msg'))) yields ["stack", "message"]

console.log(Object.keys(new Error('some msg')));
console.log(Object.getOwnPropertyNames(new Error('some msg')));
Shimon S
  • 3,353
  • 2
  • 22
  • 31
-6

Another difference is that (at least with nodejs) "getOwnPropertyNames" function does not guarantee keys order, that's why I usually use "keys" function :

    Object.keys(o).forEach(function(k) {
      if (!o.propertyIsEnumerable(k)) return;
      // do something...
    });
  • 1
    Is that still the case in current versions of Node.js, and if so, do you know any examples of `getOwnPropertyNames` not being in order? Because ES2015 specifies [an order for `Obect.getOwnPropertyNames`](http://www.ecma-international.org/ecma-262/6.0/#sec-object.getownpropertynames), while the [order for `Obect.keys`](http://www.ecma-international.org/ecma-262/6.0/#sec-object.keys) is still up to the implementation. – szupie Jun 24 '16 at 03:37
  • 7
    I always thought there was no order of JS object keys and you shouldn't rely on it even if an implementation keeps the order? – Juan Mendes Nov 08 '16 at 22:08
  • 1
    Um, I think it's the other way round; the order for getOwnPropertyNames is defined in the spec. Object.keys is up to the implementation. – tjvr Mar 12 '17 at 22:48
  • 1
    All of the following have unspecified order: `for-in loop`, `Object.keys`, and `Object.getOwnPropertyNames`. That said, all three will enumerate in a consistent order with respect to one another. – Thomas Eding Oct 03 '17 at 06:30