【问题标题】:Is there a way to abstract the setters/getters of a JS property to the Object's prototype?有没有办法将 JS 属性的 setter/getter 抽象为 Object 的原型?
【发布时间】:2018-07-17 03:04:01
【问题描述】:

我正在尝试在 Node.js 中创建一个非常简单的类。该类称为 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 的每个实例都会在内存中生成全新的 setter 和 getter,这在创建许多实例时效率非常低。

我还阅读了归因于原型对象的函数只创建一次;但是,每当我尝试将这些设置为原型时(通过替换它):

function Student(){...
    Object.defineProperties(Student.prototype, {...});
}

创建 2 个或更多实例时失败,引用“TypeError:无法重新定义属性”。 出了什么问题,我该怎么做才能使这段代码尽可能高效?最好将所有代码都放在构造函数中。

编辑:导致它失败的简单测试。

let a = new Student("A", "S", 1, [1, 2]);
let b = new Student("G", "X", 0, [3, 2]);
console.log(a.firstName);

【问题讨论】:

  • 您应该发布不起作用的实际代码。
  • 您希望每个学生的 getter 和 setter 都可以在自己的执行上下文中访问变量 _ID_courses 等。这意味着每个学生都需要有自己的 getter 和 setter,因此您根本不应该尝试在原型上使用共享的 getter 和 setter。如果您在 getter 和 setter 中使用了诸如 this._courses 之类的对象属性,那么您可以通过原型在所有学生之间共享它们(您将定义 getter/setter outside构造函数来做到这一点),但我认为这违背了你试图使用 getter/setter 的目的。

标签: javascript node.js oop object inheritance


【解决方案1】:

在构造函数中为隐私目的创建的局部变量不能被原型上的共享方法访问。这些变量不在添加到原型的方法的范围内。

而且,正如您所知道的,在构造函数中向原型添加内容也不会起作用。最好的办法(如果它没有因错误而失败)是创建一个所有对象都使用的方法,该方法只能访问最后创建的对象(这真的很糟糕且具有误导性)。

构造函数中的私有属性只能通过在构造函数范围内单独添加到对象的方法访问(这只是声明变量的普通 Javascript 范围规则),这意味着复制方法。

因此,您必须选择要优化的内容。要么你在构造函数中声明了私有变量,要么你在原型上使用的方法只能访问对象的常规属性,但是你不能在原型上拥有可以直接访问构造函数中的私有变量的方法。

【讨论】:

  • @ajax992 - 这回答了你的问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2023-03-20
  • 2012-01-31
  • 2012-06-10
相关资源
最近更新 更多