4
class Polygon {
  constructor() {
    this.name = "Polygon";
  }
}
class Square extends Polygon {
  constructor() {
    super();
  }
}
console.log(Square.__proto__ === Polygon); // true  why?
console.log(Square.prototype.__proto__ === Polygon.prototype); // true

I can understand the second print statement being true, but I don't understand the first print statement being true.

desen zhao
  • 157
  • 6
  • why do you need this? mdn says it's deprecated: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto – RudyMartin Jun 24 '23 at 13:53
  • Or rather, I don't understand why Square's [[Prototype]] is Polygon? @RudyMartin – desen zhao Jun 24 '23 at 13:58
  • https://stackoverflow.com/questions/28674356/6to5-compiler-use-proto-for-inheritance https://stackoverflow.com/questions/30783217/what-benefits-does-es2015-es6-class-syntax-provide – Bergi Jun 24 '23 at 14:57

2 Answers2

3

It's so static fields/accessors/methods can be looked up on the parent class if it's not found on the child, for example:

class Polygon {
  constructor() {
    this.name = "Polygon";
  }
  
  static staticPolygonMethod() {
    return "staticPolygon";
  }
}
class Square extends Polygon {
  constructor() {
    super();
  }
}

console.log(Square.staticPolygonMethod()); // staticPolygon

As static fields/accessors/methods are added to the class itself, the staticPolygonMethod is set on Polygon class/function itself.

In this example above, staticPolygonMethod is not found on the Square class/function, so its [[Prototype]] is checked for the property, which is set to Polygon, as you've seen with the Square.__proto__ === Polygon check. Because staticPolygonMethod exists on the Polygon class/function, it can now be found correctly in Square's prototype chain and thus used as expected on Square.

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • In other words, the extends keyword sets Polygon as the [[Prototype]] of Square. @NickParsons – desen zhao Jun 24 '23 at 15:25
  • @desenzhao Yes, you shouldn't expect `Square` to have a `[[Prototype]]` of `Polygon` if it's not being extended. When nothing is extended then the class's `[[Prototype]]` will be `Function.prototype` – Nick Parsons Jun 25 '23 at 03:34
2

The extends keyword sets up two prototype chains:

  • Sets parentClass.prototype object as the prototype of the childClass.prototype

  • Sets parentClass constructor as the prototype of the childClass constructor

In your case, the two prototype chains that extends keyword forms are as shown below:

Square.prototype ---> Polygon.prototype ---> Object.prototype

Square ---> Polygon ---> Function.prototype ---> Object.prototype

The second point is related to your question and it is done to allow the lookup of static properties on the parent constructor.

Yousaf
  • 27,861
  • 6
  • 44
  • 69