Есть ли способ абстрагировать сеттеры / геттеры свойства JS к прототипу объекта?

1

Я пытаюсь создать очень простой класс в узле. Класс называется 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);
  • 0
    Вы должны опубликовать фактический код, который не работает.
  • 0
    Вы хотите, чтобы получатели и установщики каждого ученика имели доступ к переменным _ID , _courses т. Д. В их собственном контексте выполнения. Это означает, что у каждого учащегося должны быть свои собственные методы получения и установки, поэтому вы не должны пытаться использовать общие для прототипа вообще. Если бы вы использовали свойства объекта, такие как this._courses в своих this._courses получения и установки, то вы могли бы поделиться ими со всеми учащимися с помощью прототипа (для этого вы должны определить методы получения / установки вне конструктора), но я думаю, что это противоречит цели что вы пытаетесь использовать геттеры / сеттеры для в любом случае.
Теги:
object
oop
inheritance

1 ответ

0

Локальные переменные, созданные в конструкторе для обеспечения конфиденциальности, не могут быть доступны с помощью общих методов прототипа. Эти переменные не входят в объем методов, добавленных в прототип.

И, как вы поняли, добавление объектов к прототипу в конструкторе тоже не сработает. Лучшее, что могло бы сделать (если оно не сбой с ошибкой), - создать единый метод, который использует все объекты, которые имеют доступ только к последнему созданному объекту (что действительно плохо и вводит в заблуждение).

Частные свойства в конструкторе могут быть доступны только с помощью методов, добавленных индивидуально к объекту в пределах области конструктора (это только обычные правила определения Javascript для объявленных переменных), что означает создание дубликатов копий методов.

Итак, вы должны выбрать то, что хотите оптимизировать. Либо у вас есть частные переменные, объявленные в конструкторе, либо вы используете методы прототипа, которые имеют доступ только к обычным свойствам объекта, но вы не можете иметь методы на прототипе, которые могут напрямую обращаться к этим частным переменным в конструкторе.

  • 0
    @ ajax992 - Это ответило на ваш вопрос?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню