Ситуация: в проекте мы решили использовать всю мощь ООП — с классами, конструкторами и всем остальным. В самом начале мы создаём класс и добавляем туда поле, к которому будем обращаться в будущем. Перед тем как писать конструктор, решаем проверить код и убедиться, что он действительно создаёт новый класс и с ним всё в порядке:
class ClassWithPrivateField {
#privateField;
constructor() {}
}
this.#privateField = 42;
Но после запуска получаем странную ошибку:
❌ Uncaught Error: Cannot read private member #privateField from an object whose class did not declare it
Может, это только в Хроме так? Пробуем запустить этот же код в Сафари и получаем сообщение об ошибке уже другого типа:
❌ SyntaxError: Cannot reference undeclared private names: "#privateField"
Странно, откуда появилась ошибка и почему браузеры обрабатывают её по-разному?
Что это значит: браузер сообщает нам, что мы пытаемся обратиться к чему-то необъявленному, в нашем случае — к полю #privateField, которое мы объявили внутри класса.
Когда встречается: в ситуациях, когда по какой-то причине браузер не может получить доступ к объекту и считает, что мы его ещё не объявили до этого в коде.
Что делать с ошибкой Uncaught Error: Cannot read private member from an object whose class did not declare it
В нашем случае ошибка в том, что с помощью символа решётки # мы объявляем приватное поле, доступ к которому возможен только изнутри класса. Если мы попробуем обратиться к нему снаружи, в основном коде скрипта (как мы и сделали), то JavaScript его просто не увидит.
Если нам нужно использовать приватное поле, нам нужно перенести его использование внутрь класса, например в конструктор:
class ClassWithPrivateField {
#privateField;
constructor() {
this.#privateField = 42;
}
}
Как видим, ошибка сразу исчезла: