Matthew Harwood Matthew Harwood - 6 months ago 13
Javascript Question

Why would the ES6 class syntax console log differently than an es5 class syntax?

Trying to learn ES6 more and inheritance a bit better.

Question: When I console log out

bob
vs
daisy
they differ.
bob
logs a prototype under
__proto__
and shows his constructor of
run:true;
. On the ES6 implementation
daisy
has no
__proto__
however, it's still has
isRunning
accessible? Why?

enter image description here

var Man = (function(){
"use strict";
function Man() {
this.run = true
}

Man.prototype.isRunning = function() {
console.log('yesss imma run');
};

return Man;
})();

var bob = new Man();
console.log(bob);

class Woman {
constructor(){
this.run = true;
}

isRunning() {
console.log('yess imma run');
}
}

var daisy = new Woman();
console.log(daisy);

Answer

It's because methods defined in ES6 classes are non enumerable. In a Man object, isRunning is enumerable, but not in Woman. And Chrome has a specific way of handling the console log. Depending on the presence of enumerable properties or not will affect the display.

The difference in the console display is trivial, but it shows an interesting difference in the way classes are built with ES6 Class. To see it more clearly, you can try to either make Man isRunning non enumerable or Woman isRunning enumerable, it should give the same output in the console. Like this for non enumerable in Man:

var Man = (function() {
     "use strict";

     function Man() {
       this.run = true
     }

     Object.defineProperty(Man.prototype, 'isRunning', {
       value: function() {
         console.log('yesss imma run');
       },
       enumerable: false
     });

     return Man;
   })();

   
   bob = new Man();
   console.log(bob);

   class Woman {
     constructor() {
       this.run = true;
     }

     isRunning() {
       console.log('yess imma run');
     }
   }

   daisy = new Woman();
   console.log(daisy);

Or enumerable in Woman:

   var Man = (function() {
     "use strict";

     function Man() {
       this.run = true
     }

     Man.prototype.isRunning = function() {
       console.log('yesss imma run');
     };

     return Man;
   })();


   bob = new Man();
   console.log(bob);

   class Woman {
     constructor() {
       this.run = true;
     }

     isRunning() {
       console.log('yess imma run ');
     }
   }
   Object.defineProperty(Woman.prototype, 'isRunning', {
     enumerable: true
   });
   daisy = new Woman();
   console.log(daisy);

EDIT:

Note that initial drafts of ES6 had enumerable set to true by default, but it was change, it's a design decision. You can see discussions leading to that decision here: https://esdiscuss.org/topic/classes-and-enumerability

Basically, native prototypes usually have non enumerable methods, so it made sense to have the same behavior with user defined classes.

This decision was introduced in draft rev 32. http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#february_2_2015_draft_rev_32