Property getters and setters - The Modern JavaScript Tutorial

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

Getters and setters ... Accessor properties are represented by “getter” and “setter” methods. In an object literal they are denoted by get and set ... ENARعربيENEnglishESEspañolFRFrançaisIDIndonesiaITItalianoJA日本語KO한국어RUРусскийTRTürkçeUKУкраїнськаZH简体中文Wewanttomakethisopen-sourceprojectavailableforpeopleallaroundtheworld.Helptotranslatethecontentofthistutorialtoyourlanguage! BuyEPUB/PDFSearchSearchTutorialmapLightthemeDarkthemeShareعربيEnglishEspañolFrançaisIndonesiaItaliano日本語한국어РусскийTürkçeУкраїнська简体中文Therearetwokindsofobjectproperties. Thefirstkindisdataproperties.Wealreadyknowhowtoworkwiththem.Allpropertiesthatwe’vebeenusinguntilnowweredataproperties. Thesecondtypeofpropertiesissomethingnew.It’saccessorproperties.Theyareessentiallyfunctionsthatexecuteongettingandsettingavalue,butlooklikeregularpropertiestoanexternalcode. GettersandsettersAccessorpropertiesarerepresentedby“getter”and“setter”methods.Inanobjectliteraltheyaredenotedbygetandset: letobj={ getpropName(){ //getter,thecodeexecutedongettingobj.propName }, setpropName(value){ //setter,thecodeexecutedonsettingobj.propName=value } }; Thegetterworkswhenobj.propNameisread,thesetter–whenitisassigned. Forinstance,wehaveauserobjectwithnameandsurname: letuser={ name:"John", surname:"Smith" }; NowwewanttoaddafullNameproperty,thatshouldbe"JohnSmith".Ofcourse,wedon’twanttocopy-pasteexistinginformation,sowecanimplementitasanaccessor: letuser={ name:"John", surname:"Smith", getfullName(){ return`${this.name}${this.surname}`; } }; alert(user.fullName);//JohnSmith Fromtheoutside,anaccessorpropertylookslikearegularone.That’stheideaofaccessorproperties.Wedon’tcalluser.fullNameasafunction,wereaditnormally:thegetterrunsbehindthescenes. Asofnow,fullNamehasonlyagetter.Ifweattempttoassignuser.fullName=,therewillbeanerror: letuser={ getfullName(){ return`...`; } }; user.fullName="Test";//Error(propertyhasonlyagetter) Let’sfixitbyaddingasetterforuser.fullName: letuser={ name:"John", surname:"Smith", getfullName(){ return`${this.name}${this.surname}`; }, setfullName(value){ [this.name,this.surname]=value.split(""); } }; //setfullNameisexecutedwiththegivenvalue. user.fullName="AliceCooper"; alert(user.name);//Alice alert(user.surname);//Cooper Astheresult,wehavea“virtual”propertyfullName.Itisreadableandwritable. AccessordescriptorsDescriptorsforaccessorpropertiesaredifferentfromthosefordataproperties. Foraccessorproperties,thereisnovalueorwritable,butinsteadtherearegetandsetfunctions. Thatis,anaccessordescriptormayhave: get–afunctionwithoutarguments,thatworkswhenapropertyisread, set–afunctionwithoneargument,thatiscalledwhenthepropertyisset, enumerable–sameasfordataproperties, configurable–sameasfordataproperties. Forinstance,tocreateanaccessorfullNamewithdefineProperty,wecanpassadescriptorwithgetandset: 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 Pleasenotethatapropertycanbeeitheranaccessor(hasget/setmethods)oradataproperty(hasavalue),notboth. Ifwetrytosupplybothgetandvalueinthesamedescriptor,therewillbeanerror: //Error:Invalidpropertydescriptor. Object.defineProperty({},'prop',{ get(){ return1 }, value:2 }); Smartergetters/settersGetters/setterscanbeusedaswrappersover“real”propertyvaluestogainmorecontroloveroperationswiththem. Forinstance,ifwewanttoforbidtooshortnamesforuser,wecanhaveasetternameandkeepthevalueinaseparateproperty_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="";//Nameistooshort... So,thenameisstoredin_nameproperty,andtheaccessisdoneviagetterandsetter. Technically,externalcodeisabletoaccessthenamedirectlybyusinguser._name.Butthereisawidelyknownconventionthatpropertiesstartingwithanunderscore"_"areinternalandshouldnotbetouchedfromoutsidetheobject. UsingforcompatibilityOneofthegreatusesofaccessorsisthattheyallowtotakecontrolovera“regular”datapropertyatanymomentbyreplacingitwithagetterandasetterandtweakitsbehavior. Imaginewestartedimplementinguserobjectsusingdatapropertiesnameandage: functionUser(name,age){ this.name=name; this.age=age; } letjohn=newUser("John",25); alert(john.age);//25 …Butsoonerorlater,thingsmaychange.Insteadofagewemaydecidetostorebirthday,becauseit’smorepreciseandconvenient: functionUser(name,birthday){ this.name=name; this.birthday=birthday; } letjohn=newUser("John",newDate(1992,6,1)); Nowwhattodowiththeoldcodethatstillusesageproperty? Wecantrytofindallsuchplacesandfixthem,butthattakestimeandcanbehardtodoifthatcodeisusedbymanyotherpeople.Andbesides,ageisanicethingtohaveinuser,right? Let’skeepit. Addingagetterforagesolvestheproblem: functionUser(name,birthday){ this.name=name; this.birthday=birthday; //ageiscalculatedfromthecurrentdateandbirthday Object.defineProperty(this,"age",{ get(){ lettodayYear=newDate().getFullYear(); returntodayYear-this.birthday.getFullYear(); } }); } letjohn=newUser("John",newDate(1992,6,1)); alert(john.birthday);//birthdayisavailable alert(john.age);//...aswellastheage Nowtheoldcodeworkstooandwe’vegotaniceadditionalproperty. PreviouslessonNextlessonShareTutorialmapCommentsreadthisbeforecommenting…Ifyouhavesuggestionswhattoimprove-pleasesubmitaGitHubissueorapullrequestinsteadofcommenting.Ifyoucan'tunderstandsomethinginthearticle–pleaseelaborate.Toinsertfewwordsofcode,usethetag,forseverallines–wrapthemin

tag,formorethan10lines–useasandbox(plnkr,jsbin,codepen…)ChapterObjectpropertiesconfigurationLessonnavigationGettersandsettersAccessordescriptorsSmartergetters/settersUsingforcompatibilityCommentsShareEditonGitHub© 2007—2022 IlyaKantorabouttheprojectcontactustermsofusageprivacypolicy



請為這篇文章評分?