属性的getter 和setter - 现代JavaScript 教程

文章推薦指數: 80 %
投票人數:10人

访问器属性由“getter” 和“setter” 方法表示。

在对象字面量中,它们用 get 和 set 表示:. let obj = { get propName() { // 当读取obj.propName 时,getter 起作用 } ... ZHARعربيENEnglishESEspañolFRFrançaisIDIndonesiaITItalianoJA日本語KO한국어RUРусскийTRTürkçeUKУкраїнськаZH简体中文我们希望将这个开源项目提供给全世界的人。

请帮助我们将教程的内容翻译为你所掌握的语言对应的版本。

购买EPUB/PDF搜索搜索教程路线图LightthemeDarktheme分享عربيEnglishEspañolFrançaisIndonesiaItaliano日本語한국어РусскийTürkçeУкраїнська简体中文有两种类型的对象属性。

第一种是数据属性。

我们已经知道如何使用它们了。

到目前为止,我们使用过的所有属性都是数据属性。

第二种类型的属性是新东西。

它是访问器属性(accessorproperties)。

它们本质上是用于获取和设置值的函数,但从外部代码来看就像常规属性。

getter和setter访问器属性由“getter”和“setter”方法表示。

在对象字面量中,它们用get和set表示: letobj={ getpropName(){ //当读取obj.propName时,getter起作用 }, setpropName(value){ //当执行obj.propName=value操作时,setter起作用 } }; 当读取obj.propName时,getter起作用,当obj.propName被赋值时,setter起作用。

例如,我们有一个具有name和surname属性的对象user: letuser={ name:"John", surname:"Smith" }; 现在我们想添加一个fullName属性,该属性值应该为"JohnSmith"。

当然,我们不想复制粘贴已有的信息,因此我们可以使用访问器来实现: letuser={ name:"John", surname:"Smith", getfullName(){ return`${this.name}${this.surname}`; } }; alert(user.fullName);//JohnSmith 从外表看,访问器属性看起来就像一个普通属性。

这就是访问器属性的设计思想。

我们不以函数的方式调用user.fullName,我们正常读取它:getter在幕后运行。

截至目前,fullName只有一个getter。

如果我们尝试赋值操作user.fullName=,将会出现错误: letuser={ getfullName(){ return`...`; } }; user.fullName="Test";//Error(属性只有一个getter) 让我们通过为user.fullName添加一个setter来修复它: letuser={ name:"John", surname:"Smith", getfullName(){ return`${this.name}${this.surname}`; }, setfullName(value){ [this.name,this.surname]=value.split(""); } }; //setfullName将以给定值执行 user.fullName="AliceCooper"; alert(user.name);//Alice alert(user.surname);//Cooper 现在,我们就有一个“虚拟”属性。

它是可读且可写的。

访问器描述符访问器属性的描述符与数据属性的不同。

对于访问器属性,没有value和writable,但是有get和set函数。

所以访问器描述符可能有: get——一个没有参数的函数,在读取属性时工作, set——带有一个参数的函数,当属性被设置时调用, enumerable——与数据属性的相同, configurable——与数据属性的相同。

例如,要使用defineProperty创建一个fullName访问器,我们可以使用get和set来传递描述符: letuser={ name:"John", surname:"Smith" }; Object.defineProperty(user,'fullName',{ get(){ return`${this.name}${this.surname}`; }, set(value){ [this.name,this.surname]=value.split(""); } }); alert(user.fullName);//JohnSmith for(letkeyinuser)alert(key);//name,surname 请注意,一个属性要么是访问器(具有get/set方法),要么是数据属性(具有value),但不能两者都是。

如果我们试图在同一个描述符中同时提供get和value,则会出现错误: //Error:Invalidpropertydescriptor. Object.defineProperty({},'prop',{ get(){ return1 }, value:2 }); 更聪明的getter/settergetter/setter可以用作“真实”属性值的包装器,以便对它们进行更多的控制。

例如,如果我们想禁止太短的user的name,我们可以创建一个settername,并将值存储在一个单独的属性_name中: letuser={ getname(){ returnthis._name; }, setname(value){ if(value.length<4){ alert("Nameistooshort,needatleast4characters"); return; } this._name=value; } }; user.name="Pete"; alert(user.name);//Pete user.name="";//Name太短了…… 所以,name被存储在_name属性中,并通过getter和setter进行访问。

从技术上讲,外部代码可以使用user._name直接访问name。

但是,这儿有一个众所周知的约定,即以下划线"_"开头的属性是内部属性,不应该从对象外部进行访问。

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

想象一下,我们开始使用数据属性name和age来实现user对象: functionUser(name,age){ this.name=name; this.age=age; } letjohn=newUser("John",25); alert(john.age);//25 ……但迟早,情况可能会发生变化。

我们可能会决定存储birthday,而不是age,因为它更精确,更方便: functionUser(name,birthday){ this.name=name; this.birthday=birthday; } letjohn=newUser("John",newDate(1992,6,1)); 现在应该如何处理仍使用age属性的旧代码呢? 我们可以尝试找到所有这些地方并修改它们,但这会花费很多时间,而且如果其他很多人都在使用该代码,那么可能很难完成所有修改。

而且,user中有age是一件好事,对吧? 那我们就把它保留下来吧。

为age添加一个getter来解决这个问题: functionUser(name,birthday){ this.name=name; this.birthday=birthday; //年龄是根据当前日期和生日计算得出的 Object.defineProperty(this,"age",{ get(){ lettodayYear=newDate().getFullYear(); returntodayYear-this.birthday.getFullYear(); } }); } letjohn=newUser("John",newDate(1992,6,1)); alert(john.birthday);//birthday是可访问的 alert(john.age);//……age也是可访问的 现在旧的代码也可以工作,而且我们还拥有了一个不错的附加属性。

上一节下一节分享教程路线图评论在评论之前先阅读本内容…如果你发现教程有错误,或者有其他需要修改和提升的地方—请提交一个GitHubissue或pullrequest,而不是在这评论。

如果你对教程的内容有不理解的地方—请详细说明。

使用标签插入只有几个词的代码,插入多行代码可以使用

标签,对于超过10行的代码,建议你使用沙箱(plnkr,JSBin,codepen…)章节对象属性配置课程导航getter和setter访问器描述符更聪明的getter/setter兼容性评论分享在GitHub上编辑© 2007—2022 IlyaKantor关于本项目联系我们



請為這篇文章評分?