1

I was reading up on ES6 classes, and it is said to be just syntactic sugar. Then why does calling Object.keys on Class.prototype not list the methods of the class?

class Class { whoami() { return "class"; } }

function Proto() {}
Proto.prototype.whoami = function () { return "proto"; }

console.log(Class.prototype); // { constructor: f() {}, whoami: f() {} }
console.log(Proto.prototype); // { constructor: f() {}, whoami: f() {} }

console.log(Object.keys(Class.prototype)); // []              <--- WHY ???
console.log(Object.keys(Proto.prototype)); // ["whoami"]
kumarchandresh
  • 559
  • 2
  • 16
  • 1
    Because methods from a `class` declaration are made non-enumerable properties of the prototype object. – Pointy Aug 12 '23 at 12:22
  • @Pointy Is that standard or depends on the platform? – kumarchandresh Aug 12 '23 at 12:25
  • 1
    It is the standard. When directly adding properties to a prototype as in your second example, it's a good idea to do that with `Object.defineProperty()`, which by default will make the added properties non-enumerable. – Pointy Aug 12 '23 at 12:27

1 Answers1

2

The difference you're observing between Object.keys(Class.prototype) and Object.keys(Proto.prototype) has to do with how class methods are defined and stored in ES6 classes compared to traditional prototype-based objects.

In your example, Class is an ES6 class, and Proto is a traditional constructor function with a manually defined prototype.

When you define a method in an ES6 class using the shorthand syntax, like whoami() { return "class"; }, the method is added to the class prototype. However, these methods are not enumerable by default, which means they won't show up when you iterate over the object's properties using Object.keys().

This is a design choice made to mimic the behavior of class methods in other programming languages like Java. In most cases, you don't want these internal methods to be visible when iterating through an object's keys.

If you want to make the methods enumerable (and thus appear in Object.keys(Class.prototype)), you can explicitly set the method's property descriptor to be enumerable

When you manually define a method on the prototype of a constructor function like Proto.prototype.whoami = function () { return "proto"; }, the method is added to the prototype with the enumerable property set to true by default. This is why you see the method in Object.keys(Proto.prototype).

pwoltschk
  • 550
  • 1
  • 3
  • 22