5

I recently came across this great post by Dr. Axel Rauschmayer:

http://www.2ality.com/2015/02/es6-classes-final.html

The following snippet roughly describes how ECMAScript 6 prototype chains work from an ECMAScript 5 point of view (section 4.2 of the original post):

// ECMAScript 6
class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    ···
}

class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y);
        this.color = color;
    }
    ···
}

let cp = new ColorPoint(25, 8, 'green');

"Under the hood" view in ECMAScript 5:

 // ECMAScript 5
 // Instance is allocated here
function Point(x, y) {
    // Performed before entering this constructor:
    this = Object.create(new.target.prototype);

    this.x = x;
    this.y = y;
}
···

function ColorPoint(x, y, color) {
    // Performed before entering this constructor:
    this = uninitialized;

    this = Reflect.construct(Point, [x, y], new.target); // (A)
        // super(x, y);

    this.color = color;
}
Object.setPrototypeOf(ColorPoint, Point);
···

let cp = Reflect.construct( // (B)
             ColorPoint, [25, 8, 'green'],
             ColorPoint);
    // let cp = new ColorPoint(25, 8, 'green');

While in the code above I understand that this is valid:

Object.getPrototypeOf(ColorPoint) === Point  //true

because of this:

Object.setPrototypeOf(ColorPoint, Point);

I'm struggling to understand why this is also true since I can't find any "ES5" explanation:

Object.getPrototypeOf(ColorPoint.prototype) === Point.prototype   // true

Maybe a line like this is missing..?

Object.setPrototypeOf(ColorPoint.prototype, Point.prototype);

Thank you all in advance.

stratis
  • 7,750
  • 13
  • 53
  • 94
  • The effect is the same as using `Object.setPrototypeOf(...)`, which assigns the internal `[[Prototype]]` property. The engine will just modify that property directly without needing to represent the step in JavaScript with `setPrototypeOf()`. – Jonathan Lonowski Jun 02 '15 at 15:11
  • 1
    ES6 does not use `setPrototypeOf` under the hood, it's only a method introduced to standardize the deprecated, non-standard `__proto__` feature and its use is discouraged for performance reasons. – the8472 Jun 02 '15 at 15:41
  • FYI, `Object.setPrototypeOf(ColorPoint, Point);` is taking care of inheriting *static* methods. – Felix Kling Jun 02 '15 at 18:31

1 Answers1

5

That "under-the-hood view" from the ES5 perspective doesn't include those lines - it's hidden in the ... sections. The point of this code is to explain the differences from ES5 inheritance, which are all about this initialisation, new.target, super behaviour, and constructor functions inheriting from other constructor functions.

The basic ES5 inheritance for the prototypes is still in place, and works like it always did:

ColorPoint.prototype = Object.create(Point.prototype, {
    constructor: {value:ColorPoint, writable:true, enumerable:false, configurable:true}
});
// ... further method definitions
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I guess you meant `ColorPoint.prototype`. Also could you tell me why the contructor's property value is set to `Point` and not restored to `ColorPoint`? – stratis Jun 02 '15 at 15:36
  • @Konos5: Ooops, of course. Very attentive, thank you! – Bergi Jun 02 '15 at 15:38
  • Fair enough. Could you also tell me where is this code taking place? Could it be automatically invoked once `extends` is encountered? – stratis Jun 02 '15 at 15:40
  • Yes, the `Object.create(Point.prototype)` is taking place as soon as the `extends` is encountered, but the `ColorPoint` function instantiation and `.prototype` assignment and `.constructor` property creation are taking place as soon as the `constructor(){…}` method of the class is encountered. – Bergi Jun 02 '15 at 16:03
  • But actually order doesn't matter here (and obviously ES5 is not exactly enough to describe all the details). The order of actions in ES6 only matters if something throws an error in the process. – Bergi Jun 02 '15 at 16:08