有没有办法将JS属性的setter / getter抽象为Object的原型?

时间:2018-02-06 23:03:21

标签: javascript node.js oop object inheritance

我正在尝试在Node中创建一个非常简单的类。该类称为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);

1 个答案:

答案 0 :(得分:0)

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

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

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

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