11

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);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Armeen Moon
  • 18,061
  • 35
  • 120
  • 233
  • Is this really the right interpretation of `use strict` inside [a function definition?](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) I presume this is ecmascript-6 (ES6) code, but aren't you comparing ES6 strict vs non-strict, and not ES5 vs ES6 ? – zipzit May 15 '16 at 21:36
  • I'm getting this behaviour on jsfiddle, codepen however is logging both with a `_proto_`: http://codepen.io/anon/pen/gryyWg – Brad Colthurst May 15 '16 at 21:36
  • 3
    The behavior of the console is not standardized. It's completely implementation dependent. – Oriol May 15 '16 at 21:38
  • Ah of course, that makes sense – Brad Colthurst May 15 '16 at 21:45
  • 1
    Do a `console.dir(daisy)` instead. – Felix Kling May 16 '16 at 02:45

1 Answers1

15

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

Julien Grégoire
  • 16,864
  • 4
  • 32
  • 57