7

Posting the following code into the Babel REPL

class Test {

}

class Test2 extends Test {

}

you get this inherits function

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

It looked fine to me until I realized it was doing both Object.create on the prototype and a setPrototypeOf call. I wasn't that familiar with setPrototypeOf so I went to the MDN where it says:

If you care about performance you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().

Which is confusing to me since they use both. Why is this the case?

Should the line instead be

if (superClass && !superClass.prototype)

for when the prototype is unset, but it still has a __proto__?

Ry-
  • 218,210
  • 55
  • 464
  • 476
m0meni
  • 16,006
  • 16
  • 82
  • 141

1 Answers1

9

The setPrototypeOf does set the [[prototype]] of subClass from its original value Function.prototype to superClass, to let it inherit static properties from it.

Object.create cannot be used here (like it is for the .prototype object), as it does not allow to create functions. The constructor of a class has to be a function though, obviously; and the only way to do that is to create functions using standard expressions/declarations and then change its prototype afterwards.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Hmmm this is a bit confusing to me. Could you create a code example of the shortcomings of `Object.create()`? From what I read on [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create), it will inherit static methods since those are just methods defined on the prototype of the original class right? – m0meni Jun 20 '16 at 16:29
  • 1
    @AR7: Static methods are defined on the constructor function object of the class, not the `.prototype` object. We are talking about the constructors inheriting from each other here, not the prototype chain of instances. – Bergi Jun 20 '16 at 16:34
  • Oh so by static you meant [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static). So `Object.create` does let you inherit the prototype methods, but not methods defined using the `static` keyword, correct? Although I'm curious...why are static methods stored on the `__proto__` object instead of the prototype? – m0meni Jun 20 '16 at 16:40
  • 1
    Well you can do `Object.create(superClass)`, but that creates an object (as the method name says) not the `subClass` function. Static methods are not stored on any `__proto__`, they're stored on the constructor itself. They are not stored on the `.prototype` because they are not supposed to be inherited by instances. – Bergi Jun 20 '16 at 16:47
  • "They are not stored on the .prototype because they are not supposed to be inherited by instances." This confused me a bit more. How is this different from "The setPrototypeOf does set the [[prototype]] of subClass from it's original value Function.prototype to superClass, to let it inherit static properties from it." I thought the whole point was to inherit the static methods? – m0meni Jun 20 '16 at 16:49
  • 2
    The [[prototype]] from which properties are inherited is a different thing than the `.prototype` property of constructors. http://stackoverflow.com/q/9959727/1048572 – Bergi Jun 20 '16 at 16:53
  • 2
    @AR7 [Here's an example showing how static methods work.](https://jsfiddle.net/dk35aasr/) Essentially, you can only access them by referencing the "class" itself, not through any instances of that class. That's why you don't want them on the prototype. – Mike Cluck Jun 20 '16 at 16:56