Почему обработка частных полей не работает ожидаемым образом в JavaScript?

Я думаю, что следующий (упрощенный) код должен работать:

class WfConfigurable {
    constructor(config) {
        this._init(config);
    }
    _init(config) {
        this.configure(config);
    }
    configure(config) {}
}

class WfStateful extends WfConfigurable {
    #saveSuspend = 0;
    constructor(config) {
        super(config);
    }
    get saving() { return this.#saveSuspend == 0; }
    configure(config) {
        this.suspendSave();
        super.configure(config);
        this.continueSave();
    }
    suspendSave() {
        this.#saveSuspend++;
    }
    continueSave(force) {
        if (force) {
            this.#saveSuspend = 0;
        } else {
            this.#saveSuspend = Math.max(this.#saveSuspend - 1, 0);
        }
    }
}

class WfApp extends WfStateful {
    constructor(config) {
        super(config);
    }
}

const wfApp = new WfApp({});

Но я получил следующее сообщение об ошибке:

Ошибка типа: невозможно прочитать частный член #saveSuspend из объекта, класс которого его не объявил
в WfApp.suspendSave ((индекс):24:13)
в WfApp.configure ((индекс):19:14)
в WfApp._init ((индекс):7:14)
в новом WfConfigurable ((индекс): 4:14)
в новом WfStateful ((индекс):15:9)
в новом WfApp ((индекс):37:9)
в (индекс):41:15

Например, это хорошо работает:

class A {
    #priv = 'hello';
    constructor() {
        console.info('A');
    }
    get priv() {
        return this.#priv;
    }
    set priv(p) {
        this.#priv = p;
    }
}

class B extends A {}

const b = new B();
b.priv += ' babe';
console.info(b.priv);

Пишет: «привет, детка»

Что такое стек ошибок?

Daniel A. White 06.07.2024 22:54

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

Pointy 06.07.2024 22:57

@DanielA.White Не думаю, что это поможет, но я добавил стек ошибок.

Nagy Zoltán 06.07.2024 23:28

Что на самом деле делает configure? Почему бы просто не сделать это в своем конструкторе?

Bergi 07.07.2024 00:00

@Bergi В этом упрощенном коде он ничего не делает. Но в реальном коде он настроит объект, и я хочу сделать его вызываемым отдельно, даже после времени создания.

Nagy Zoltán 07.07.2024 00:17
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сообщение об ошибке «Невозможно прочитать закрытый член #saveSuspend из объекта, класс которого не объявил его» немного сбивает с толку. Более точным в этом случае было бы «из объекта, где он (еще) не инициализирован».

Частные поля и поля в целом создаются в экземпляре (и инициализируются значением, определенным в теле класса), когда конструктор super() завершает работу. Если этот конструктор вызывает переопределенный метод (configure) до завершения инициализации, он не сможет получить доступ к несуществующему полю. В случае с частными полями он просто выдает исключение, поскольку поле не существует, вместо того, чтобы возвращать undefined, как обычное свойство.

Единственное решение — никогда не вызывать переопределяемый метод из конструктора. Это верно для любого языка. В вашем случае просто избавьтесь от метода configure вообще, это не имеет значения.

Другие вопросы по теме