lastuniverse
@lastuniverse
Всегда вокруг да около IT тем

Что творится с контекстом внутри ES6 классов?

В общем вся суть вопроса - почему ломается контекст у ClassC. Я примерно понимаю, что это происходит потому что метод init вызывается из конструктора класса ClassA, но на мой взгляд это выглядит багом, так как не позволяет нормально работать с приватными методами в рамках одного класса.

Подскажите, описано ли такое поведение где нибудь в спецификации или это баг?

Если описано, то пожалуйста скиньте по возможности ссылку на описание конкретно этого поведения.

class ClassA {
    constructor(){
        this.#methidA();
        this.init();
    }
    
    init(){
    
    }

    #methidA(){
        console.log('in ClassA.#methodA');
    }
}
const a = new ClassA(); // все отлично





class ClassB extends ClassA {
    constructor(){
        super();
        this.#methidB();
    }
    
    #methidB(){
        console.log('in ClassB.#methodB');
    }
}
const b = new ClassB(); // все отлично





class ClassC extends ClassA {
    init(){
        this.#methidC(); 

    }
    
    #methidC(){
        console.log('in ClassC.#methodC');
    }
}
const c = new ClassC(); // this.#methidC(); TypeError: Receiver must be an instance of class ClassC
  • Вопрос задан
  • 142 просмотра
Решения вопроса 1
Alexandroppolus
@Alexandroppolus
кодир
Потому что во время вызова конструктора ClassA, где у тебя вызывается init из ClassC, объект ещё "не доделан", где-то внутри, до полноценного экземпляра ClassC, в частности, ему ещё не добавлены приватные методы ClassC.

Скопируй в консоль Хрома этот код:
код

class ClassA {
    constructor(){
        this.#methidA();
        this.init();
    }
    
    init(){
    
    }

    #methidA(){
        console.log('in ClassA.#methodA');
    }
}

class ClassC extends ClassA {
    init(){
        console.log('*** this in init(): ', this);
        debugger;
    }
    
    #methidC(){
        console.log('in ClassC.#methodC');
    }
    callMethidC() {
        console.log('*** this in callMethidC(): ', this);
        debugger;
        this.#methidC();
    }
}

const c = new ClassC();
c.callMethidC();



и нажми ентер.

на брекпоинтах разверни в консоли экземпляр класса, который будет в последних выводах в консоль (это надо делать именно во время остановок на брекпоинтах, иначе будет одинаково).
можно увидеть, что в первом случае в [[PrivateMethods]] не хватает метода #methidC()

приватные методы, судя по всему, хранятся не в прототипе, а в какой-то скрытой области, которую можно увидеть только вот так, в момент дебага.

надо поисследовать, почитать спецификацию. Сам их не использую, у нас на работе TS )
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы