盘点JavaScript中Getter()和Setter()函数的使用

开发 前端
Getter/setter 可以用作“真实”属性值的包装器,以便对它们进行更多的控制。

[[420607]]

大家好,我是进阶学习者。

一、前言

有两种类型的属性。

第一种是 数据属性。已经知道如何使用它们了。到目前为止,使用过的所有属性都是数据属性。

第二种类型的属性是新东西。它是 访问器属性(accessor properties)。它们本质上是用于获取和设置值的函数,但从外部代码来看就像常规属性。

二、Getter 和 setter

访问器属性由 “getter” 和 “setter” 方法表示。在对象字面量中,它们用 get和 set表示:

  1. let obj = {   
  2.     get propName() {    // 当读取 obj.propName 时,getter 起作用  
  3. },  set propName(value) {  
  4.   // 当执行 obj.propName = value 操作时,setter 起作用   
  5. }}; 

当读取 obj.propName时,getter 起作用,当 obj.propName被赋值时,setter 起作用。

例:

有一个具有 name和 surname属性的对象 user:添加一个 fullName属性,该属性值应该为 "John Smith"。当然,不想复制粘贴已有的信息,因此可以使用访问器来实现:

  1. let user = { 
  2.   name"John"
  3.   surname: "Smith"
  4.   get fullName() { 
  5.     return `${this.name} ${this.surname}`; 
  6.   } 
  7. }; 
  8. alert(user.fullName); // John Smith 

从外表看,访问器属性看起来就像一个普通属性。

这就是访问器属性的设计思想。不以函数的方式 调用 user.fullName,正常 读取 它:getter 在幕后运行。

截至目前,fullName只有一个 getter。如果尝试赋值操作 user.fullName=,将会出现错误:

  1. let user = { 
  2.   get fullName() { 
  3.     return `...`; 
  4.   } 
  5. }; 
  6. user.fullName = "Test"; // Error(属性只有一个 getter) 

让通过为 user.fullName添加一个 setter 来修复它:

  1. let user = { 
  2.   name"John"
  3.   surname: "Smith"
  4.   get fullName() { 
  5.     return `${this.name} ${this.surname}`; 
  6.   }, 
  7.   set fullName(value) { 
  8.     [this.name, this.surname] = value.split(" "); 
  9.   } 
  10. }; 
  11. // set fullName 将以给定值执行 
  12. user.fullName = "Alice Cooper"
  13. alert(user.name); // Alice 
  14. alert(user.surname); // Cooper 

现在,就有一个“虚拟”属性。它是可读且可写的。

三、访问器描述符

例:

要使用 defineProperty创建一个 fullName访问器,可以使用 get和 set来传递描述符:

  1. let user = { 
  2.   name"John"
  3.   surname: "Smith" 
  4. }; 
  5. Object.defineProperty(user'fullName', { 
  6.   get() { 
  7.     return `${this.name} ${this.surname}`; 
  8.   }, 
  9.   set(value) { 
  10.     [this.name, this.surname] = value.split(" "); 
  11.   } 
  12. }); 
  13. alert(user.fullName); // John Smith 
  14. for(let key in user) alert(key); // name, surname 

注:

一个属性要么是访问器(具有 get/set方法),要么是数据属性(具有 value),但不能两者都是。

四、更聪明的 getter/setter

Getter/setter 可以用作“真实”属性值的包装器,以便对它们进行更多的控制。

例:

如果想禁止太短的 user的 name,可以创建一个 setter name,并将值存储在一个单独的属性 _name中:

  1. let user = { 
  2.   get name() { 
  3.     return this._name; 
  4.   }, 
  5.   set name(value) { 
  6.     if (value.length < 4) { 
  7.       alert("Name is too short, need at least 4 characters"); 
  8.       return
  9.     } 
  10.     this._name = value; 
  11.   } 
  12. }; 
  13. user.name = "Pete"
  14. alert(user.name); // Pete 
  15. user.name = ""; // Name 太短了…… 

注:

从技术上讲,外部代码可以使用 user._name直接访问 name。但是,这儿有一个众所周知的约定,即以下划线 "开头的属性是内部属性,不应该从对象外部进行访问。

五、兼容性

访问器的一大用途是,它们允许随时通过使用 getter 和 setter 替换“正常的”数据属性,来控制和调整这些属性的行为。

开始使用数据属性 name和 age来实现 user 对象:

  1. function User(name, age) { 
  2.   this.name = name
  3.   this.age = age; 
  4. let john = new User("John", 25); 
  5. alert( john.age ); // 25 

但情况可能会发生变化。

可能会决定存储 birthday,而不是 age,因为它更精确,更方便:

现在应该如何处理仍使用 age属性的旧代码呢?

可以尝试找到所有这些地方并修改它们,但这会花费很多时间,而且如果其他很多人都在使用该代码,那么可能很难完成所有修改。

为 age添加一个 getter 来解决这个问题:

  1. function User(name, birthday) { 
  2.                 this.name = name
  3.                 this.birthday = birthday; 
  4.                 // 年龄是根据当前日期和生日计算得出的 
  5.                 Object.defineProperty(this, "age", { 
  6.                     get() { 
  7.                         let todayYear = new Date().getFullYear(); 
  8.                         return todayYear - this.birthday.getFullYear(); 
  9.                     } 
  10.                 }); 
  11.             } 
  12.             let john = new User("John", new Date(1992, 6, 1)); 
  13.             alert(john.birthday); // birthday 是可访问的 
  14.             alert(john.age); // ……age 也是可访问的 

现在旧的代码也可以工作,而且还拥有了一个不错的附加属性。

六、总结

本文基于JavaScript基础,介绍了getter 和 setter函数的使用。对于其中的属性,通过案例的样式,运行效果图的展示,进行详细的讲解。同时拓展相对于的内容,希望能够帮助你更好的理解。

欢迎大家积极尝试,有时候看到别人实现起来很简单,但是到自己动手实现的时候,总会有各种各样的问题,切勿眼高手低,勤动手,才可以理解的更加深刻。

代码很简单,希望对你学习有帮助。

 

责任编辑:武晓燕 来源: 前端进阶学习交流
相关推荐

2015-06-08 13:19:11

JavaScriptgettersetter

2017-07-13 10:29:53

前端JavaScriptgetter和sett

2009-06-29 17:03:41

自动生成Getter和Eclipse

2021-07-16 07:57:35

JavaScriptEval函数

2021-10-09 07:10:30

JavaScriptBigIn函数

2017-02-20 23:05:14

JavaScript

2021-11-24 07:47:06

安全

2011-07-08 10:25:55

JavaScript

2011-05-30 16:11:46

Javascript

2010-09-09 09:31:19

SQL函数left

2020-09-23 16:07:52

JavaScript函数柯里化

2021-10-09 07:10:31

JavaScript对象Python

2021-07-20 10:26:12

JavaScriptasyncawait

2021-08-10 09:57:27

JavaScriptPromise 前端

2010-09-10 13:56:25

SQLMAX()函数

2023-06-28 08:34:02

Bind()函数JavaScript

2021-09-03 10:00:00

JavaScript迭代对象

2021-06-15 10:01:27

JavaScript数组遍历Entries

2021-09-14 07:26:25

JavaScript迭代对象

2021-06-18 10:05:14

JavaScript数组遍历
点赞
收藏

51CTO技术栈公众号