Я пытаюсь создать очень простой класс в узле. Класс называется Student и содержит несколько переменных, которые я хочу сохранить частным. Таким образом, я не обозначил их как
this.field = "";
скорее
let field = "";
Я прочитал, что свойства объекта могут быть созданы внутри конструктора следующим образом:
exports.student = function Student(firstName, lastName, ID, courses){
if(courses.length < 2) throw "Not enough courses supplied!";
let _firstName= firstName || "";
let _lastName = lastName || "";
let _ID = ID || 0;
let _courses = courses || [];
Object.defineProperties(this, {
firstName: {
get: () => {return _firstName;},
set: (name) => {_firstName = name; return this}
},
lastName: {
get: () => {return _lastName},
set: (name) => {_lastName = name; return this}
},
ID: {
get: () => {return _ID},
set: (name) => {_ID = name; return this}
},
courses: {
get: () => {return _courses}
}
});
};
Что отлично работает на базовом уровне. Однако мне пришло в голову, что каждый экземпляр Student генерирует совершенно новые сеттеры и геттеры в памяти, что очень неэффективно, когда создается множество экземпляров.
Я также читаю функции, связанные с объектом Prototype, создаются только один раз; однако, всякий раз, когда я пытаюсь установить их на прототип, например, (заменив это):
function Student(){...
Object.defineProperties(Student.prototype, {...});
}
Он терпит неудачу при создании 2 или более экземпляров, ссылаясь на "TypeError: Can not redefine property". Что происходит не так, и что я могу сделать, чтобы сделать этот код максимально эффективным? Было бы предпочтительнее иметь весь код внутри функции конструктора.
Изменение: простые тесты, которые приводят к сбою.
let a = new Student("A", "S", 1, [1, 2]);
let b = new Student("G", "X", 0, [3, 2]);
console.log(a.firstName);
Локальные переменные, созданные в конструкторе для обеспечения конфиденциальности, не могут быть доступны с помощью общих методов прототипа. Эти переменные не входят в объем методов, добавленных в прототип.
И, как вы поняли, добавление объектов к прототипу в конструкторе тоже не сработает. Лучшее, что могло бы сделать (если оно не сбой с ошибкой), - создать единый метод, который использует все объекты, которые имеют доступ только к последнему созданному объекту (что действительно плохо и вводит в заблуждение).
Частные свойства в конструкторе могут быть доступны только с помощью методов, добавленных индивидуально к объекту в пределах области конструктора (это только обычные правила определения Javascript для объявленных переменных), что означает создание дубликатов копий методов.
Итак, вы должны выбрать то, что хотите оптимизировать. Либо у вас есть частные переменные, объявленные в конструкторе, либо вы используете методы прототипа, которые имеют доступ только к обычным свойствам объекта, но вы не можете иметь методы на прототипе, которые могут напрямую обращаться к этим частным переменным в конструкторе.
_ID
,_courses
т. Д. В их собственном контексте выполнения. Это означает, что у каждого учащегося должны быть свои собственные методы получения и установки, поэтому вы не должны пытаться использовать общие для прототипа вообще. Если бы вы использовали свойства объекта, такие какthis._courses
в своихthis._courses
получения и установки, то вы могли бы поделиться ими со всеми учащимися с помощью прототипа (для этого вы должны определить методы получения / установки вне конструктора), но я думаю, что это противоречит цели что вы пытаетесь использовать геттеры / сеттеры для в любом случае.