#javascript
#javascript
Вопрос:
Когда я создаю экземпляр класса через Object.create(Example.prototype)
, чтобы обойти его конструктор, больше невозможно работать с собственными частными полями:
class Example {
#myPrivateProp;
setup() {
this.#myPrivateProp = 1;
}
}
const e1 = new Example();
const e2 = Object.create(Example.prototype);
console.log(e1.setup()); // works
console.log(e2.setup()); // fails with Uncaught TypeError: Cannot write private member #myPrivateProp to an object whose class did not declare it
Есть ли способ заставить это работать, сохраняя неизменность отказа от вызова конструктора?
Для контекста вы можете увидеть эту проблему: https://github.com/mikro-orm/mikro-orm/issues/1226
Комментарии:
1. При использовании собственных частных полей нет .
2. Именно поэтому частные поля — плохая идея: они нарушают отражение. Тот, кто хочет их использовать, должен знать об этом.
3. Для вашего контекста: лицо, определяющее частное поле, также отвечает за предоставление пары
serialise
методов /deserialise
(илиtoJSON
/fromJSON
). Вы можете попробовать создать его с помощью своего декоратора, но для этого потребуется вызвать конструктор. (Что на самом деле не должно быть проблемой, если конструктор написан правильно и только инициализирует экземпляр, не выполняя побочные эффекты).
Ответ №1:
То, что вы определяете здесь, — это не частное поле, а поле частного экземпляра. Поле частного экземпляра не должно быть открыто и обработано другими, кроме этого самого экземпляра. Вы не должны иметь возможности клонировать этот самый экземпляр вместе с его состоянием, манипулировать им и заменять исходный.
У вас есть два варианта;
- Статическое приватное поле, принадлежащее
Example
классу, к которому можно обращаться и которым можно взаимно управлять любым экземпляром этого класса или даже объектами, созданными подобнымObject.create(Example.prototype)
образом .
такие как;
class Example {
static #SECRET = 0;
constructor(){
}
addOne() {
return Example.#SECRET;
}
}
i1 = new Example();
i2 = new Example();
console.log(i1.addOne()); // <- 1
console.log(i2.addOne()); // <- 2
i3 = Object.create(Example.prototype);
console.log(i3.addOne()); // <- 3
Example.#SECRET = 4; // <- Uncaught SyntaxError: Private field '#SECRET' must be
// declared in an enclosing class
- Поле частного экземпляра принадлежит экземпляру и может быть доступно и обрабатываться только этим экземпляром. Как это достигается, точно видно из вашего примера кода. Каждый отдельный экземпляр будет иметь свой собственный
#myPrivateProp
, что, если вы спросите меня, прекрасная вещь. Например, можно создать множество отдельных очередей, и их критически важные свойства не будут раскрыты.
Комментарии:
1. » не частное поле, а поле частного экземпляра». — поле частного экземпляра — это просто особый вид частного поля.
2. » Поле частного экземпляра принадлежит экземпляру и может быть доступно и обрабатываться только этим экземпляром » — это неправда. К закрытому полю можно получить доступ с помощью любого кода внутри
class
, из статических методов, а также методов, которые были вызваны в других экземплярах. Вы имели в виду «можно получить доступ только через экземпляр»? Но это ничем не отличается от обычного свойства, зависящего от конкретного экземпляра.3. Я действительно не понимаю, как это отвечает на вопрос о вызове
setup()
метода для объекта, созданного с помощьюObject.create