Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am trying to learn ECMAScript 6 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 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);
like image 866
Armeen Harwood Avatar asked May 15 '16 21:05

Armeen Harwood


1 Answers

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 changed, 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

like image 84
Julien Grégoire Avatar answered Oct 23 '22 22:10

Julien Grégoire