Property Getters and Setters

JavaScript Property Getters and Setters (JavaScript属性Getter和Setter)

In this chapter, we cover the types of object properties. (在本章中,我们将介绍对象属性的类型。)

As a rule, there exist two object property types: data properties and accessor properties. All the properties we represented before are data properties. Accessor properties are relatively new and execute on getting and setting values. However, they seem like a regular property to the external code.

The Usage of Getters and Setters

The Usage of Getters and Setters (Getter和Setter的使用)

The so-called getter and setter methods represent accessor properties. They are specified by get and set inside an object literal as shown below:

let obj = {
 get propName() {
   // getter, the code executed when obj.propName id getting
(//getter , obj.propName id获取时执行的代码)
 },
 set propName(value) {
   // setter, the code executed when obj.propName = value is setting
(//setter ,设置obj.propName = value时执行的代码)
 }
};

The getter will operate once obj.propName is read. The setter will work once it is already assigned. (读取obj.propName后, getter将运行。一旦分配完毕, SETTER将开始工作。)

An example of a user object with a name and a surname is demonstrated below:

let site = {
 siteName: "w3cdoc",
 bookName: "Javascript"
};
console.log(site);

The next step is adding a fullName property (it should be “w3cdoc Javscsript”). To avoid copy-pasting the existing information, it can be implemented as an accessor like this:

let site = {
 siteName: "w3cdoc",
 bookName: "Javascript",
 get fullName() {
   return `Welcome to ${this.siteName}, ${this.bookName} book`;
 }
};
console.log(site.fullName);

As it was told, an accessor property can look like a regular one. That’s its main idea. (正如所说,访问器属性可能看起来像普通的访问器属性。这就是它的主要理念。)

The site.fullName is not called as a function. It is read normally, and the getter is performed behind the scenes. (Site.fullName未作为函数调用。正常读取,吸气器在幕后进行。)

The attempt to assign user.fullName= will lead to an error like here:

let site = {
 get fullName() {
   return `...`;
 }
};
// Error, property has only a getter
site.fullName = "Test";

Adding a setter for site.fullName will help to fix it:

let site = {
 siteName: "w3cdoc",
 bookName: "Javascript",
 get fullName() {
   return `${this.siteName}, ${this.bookName}`;
 },
 set fullName(value) {
   [this.siteName, this.bookName] = value.split(" ");
 }
};
site.fullName = "W3 CSS"; // set fullName is executed with the given value
console.log(site.siteName); // W3
console.log(site.bookName); // CSS

The result will be having a virtual fullName property, which is both writable and readable. (结果将具有一个虚拟fullName属性,该属性既可写又可读。)

About Accessor Descriptors

About Accessor Descriptors (关于访问器描述符)

Now, let’s check out the descriptors for accessor properties. They are different from the descriptors for the data properties. There isn’t any value or writable for accessor properties. Instead, they include get and set functions. (现在,让我们查看访问器属性的描述符。 它们与数据属性的描述符不同。 访问器属性没有任何值或可写。 相反,它们包括GET和SET函数。)

An accessor descriptor may include:

  • get – a no-argument function, operating once a property is read, (- get –无参数函数,在读取属性后运行,)

  • set – a function that has a single argument, which is called once the property is set, (- set –具有单个参数的函数,在属性设置后调用,)

  • enumerable – the same as for data properties, (-可枚举–与数据属性相同,)

  • configurable– the same as for data properties. (-可配置-与数据属性相同。)

For generating a fullName accessor with defineProperty, a descriptor with get and set should be passed like this:

let user = {
 firstname: "Helen",
 lastname: "Down"
};
Object.defineProperty(user, 'fullName', {
 get() {
   return `${this.firstname} ${this.lastname}`;
 },
 set(value) {
   [this.firstname, this.lastname] = value.split(" ");
 }
});
console.log(user.fullName); // Helen Down
for (let key in user) {
 console.log(key); // name, surname
}

An important note: a property must either be an accessor property or a data property.

Trying to put both in the same descriptor will lead to an error like this:

// Error: Invalid property descriptor
Object.defineProperty({}, 'prop', {
 get() {
   return 1
(返回%1)
 },
 value: 10
});

Wider Usage of Getters and Setters

Wider Usage of Getters and Setters (Getter和Setter的更广泛使用)

Getters and setters can be usefully performed as wrappers over property values for gaining more control over operations. (Getter和setter可以作为属性值的包装器执行,以获得对操作的更多控制。)

For prohibiting very short names for the user, you may have a setter name, storing the value within a separate property _name like this:

let book = {
 get name() {
   return this._name;
 },
 set name(value) {
   if (value.length < 3) {
     console.log("Name too short, at least 4 characters needed");
     return;
   }
   this._name = value;
 }
};
book.name = "Javascript";
console.log(book.name); // Javascript
book.name = ""; // Name too short

So, the name is kept in the _name property. The access is implemented through getter and setter. (因此,名称保留在_name属性中。访问通过getter和setter实现。)

The Usage for Compatibility

The Usage for Compatibility (兼容性的用法)

Another significant use of accessors is that they allow controlling a regular data property at any moment by interchanging it with a getter and setter. Here is an example of user objects, applying name and age data properties:

function User(name, age) {
 this.name = name;
 this.age = age;
}
let david = new User("David", 30);
console.log(david.age); // 30

Now, the main issue is how to deal with the old code, which still applies the age property. (现在,主要问题是如何处理仍然应用age属性的旧代码。)

The most efficient way of solving the issue is to add a getter for the age property:

function User(name, bday) {
 this.name = name;
 this.bday = bday;
 // age is calculated based on the current date and birthday
(//年龄基于当前日期和生日计算)
 Object.defineProperty(this, "age", {
   get() {
     let todayYear = new Date().getFullYear();
     return todayYear - this.bday.getFullYear();
   }
 });
}
let david = new User("David", new Date(1990, 10, 5));
console.log(david.bday); // birthday 
console.log(david.age); // the age

So, finally, both the code works, and there is an additional useful property. (最后,这两个代码都有效,还有一个额外的有用属性。)



请遵守《互联网环境法规》文明发言,欢迎讨论问题
扫码反馈

扫一扫,反馈当前页面

咨询反馈
扫码关注
返回顶部