Search code examples
javascriptecmascript-6prototypebabeljs

Why __proto__ not the object


I put the following code to babel:

class Animal {}

class Rabbit extends Animal {}

And it transpiles it to the following:

"use strict";

function _inheritsLoose(subClass, superClass) {
  subClass.prototype = Object.create(superClass.prototype);
  subClass.prototype.constructor = subClass;
  subClass.__proto__ = superClass;
}

var Animal = function Animal() {};

var Rabbit =
  /*#__PURE__*/
  function(_Animal) {
    _inheritsLoose(Rabbit, _Animal);

    function Rabbit() {
      return _Animal.apply(this, arguments) || this;
    }

    return Rabbit;
  }(Animal);

The question is why does it use this line subClass.__proto__ = superClass; and according to docs __proto__ could be either object or null but here superClass is a function.

My question is not duplicate since, I'm not asking about object.prototype=function.prototype, but why __proto__ = typeof function instead of object or null as in spec


Solution

  • It's for static properties / methods. They are also inherited:

     class Animal {
       static test() { }
     }
    
     console.log(Rabbit.test());
    

    Now to transpile that correctly, the Rabbit constructor function has to inherit the Animal constructor function. That is usually no problem, as functions are objects too and therefore can inherit each other. Unfortunately, there is no way to create a function that inherits another, that has to be set afterwards:

     function Animal () { }
     Animal.test = function() { }
    
     function Rabbit() { }
    
     Object.setPrototypeOf(Rabbit, Animal);
    
     console.log(Rabbit.test());
    

    Now the next problem is, that Object.setPrototypeOf is quite new, just as class, so to transpile it down it can't be used. Thats where the .__proto__ property comes into play: It was once added by Chrome to change the prototype of an object, and as a lot of libraries adopted the usage, other browsers implemented it too and it was also added to the spec, although it is considered a design mistake (performance nightmare). It is the only reliable way to transpile static class properties down by now.

    In the future the browser support for class gets hopefully better and we don't have to rely on these transpilation hacks anymore.