Почему в JavaScript (супер .__ proto__ === это .__ proto__) верно? - PullRequest
10 голосов
/ 12 октября 2019

Кажется, что в JavaScript (ES6) классы super.__proto__ === this.__proto__.

Можете ли вы объяснить, почему это так? Поведение кажется одинаковым для разных браузеров, поэтому я подозреваю, что это указано где-то в спецификации.

Рассмотрим следующий код:

class Level1 {
    myFunc() {
        console.log('Level1');
    }
}

class Level2 extends Level1 {
    myFunc() {
        console.log('Level2');
    }
}

class Level3 extends Level2 {
    myFunc() {
        console.log('Level3 BEGIN ' + Math.random()); 
        super.__proto__.myFunc();
        console.log(super.__proto__ === this.__proto__);
        console.log('Level3 END'); 
    }
}

const foo = new Level3();
foo.myFunc();

Я бы ожидал, что super.__proto__.myFunc(); вызовет функцию myFunc() класса Level1 и что super.__proto__ !== this.__proto__. Вместо этого super.__proto__.myFunc(); фактически вызывает myFunc() класса Level3 (он вызывает себя), а затем при втором вызове вызывает myFunc() класса Level2. Это вполне понятно, если super.__proto__ === this.__proto__, который демонстрирует код.

Можете ли вы объяснить причину, по которой super.__proto__ === this.__proto__ в этом примере? Если возможно, просьба также предоставить ссылки на соответствующий раздел спецификации.

1 Ответ

6 голосов
/ 12 октября 2019

Object.prototype.__proto__ является собственностью с геттером [1] . Он работает на своем this значении. Нет фактического super объекта, который бы имел значение this (вы не могли бы написать Object.getPrototypeOf(super)), просто super способ поиска свойств, поэтому this.__proto__ и super.__proto__ означают то же самое, что ипока __proto__ также не определен нигде ниже в цепочке прототипов.

Сравните:

class Parent {
    get notProto() {
        return this instanceof Child;
    }
}

class Child extends Parent {
    test() {
        console.log(super.notProto);
    }
}

new Child().test();

// bonus: [1]
console.log(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...