Private properties in JavaScript ES6 classes - Stack Overflow

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

Short answer, no, there is no native support for private properties with ES6 classes. But you could mimic that behaviour by not attaching the new properties ... Home Public Questions Tags Users Collectives ExploreCollectives FindaJob Jobs Companies Teams StackOverflowforTeams –Collaborateandshareknowledgewithaprivategroup. CreateafreeTeam WhatisTeams? Teams CreatefreeTeam CollectivesonStackOverflow Findcentralized,trustedcontentandcollaboratearoundthetechnologiesyouusemost. Learnmore Teams Q&Aforwork Connectandshareknowledgewithinasinglelocationthatisstructuredandeasytosearch. Learnmore PrivatepropertiesinJavaScriptES6classes AskQuestion Asked 8yearsago Modified today Viewed 343ktimes 523 153 IsitpossibletocreateprivatepropertiesinES6classes? Here'sanexample. HowcanIpreventaccesstoinstance.property? classSomething{ constructor(){ this.property="test"; } } varinstance=newSomething(); console.log(instance.property);//=>"test" javascriptclassecmascript-6private-memberses2022 Share Follow editedFeb23at18:16 RohìtJíndal 14.1k1111goldbadges6161silverbadges104104bronzebadges askedMar3,2014at20:08 d13d13 10.1k1212goldbadges3535silverbadges3939bronzebadges 3 7 Thereisactuallystage3proposalforthisfeature-tc39.github.io/proposal-class-fieldsgithub.com/tc39/proposal-class-fields – arty Jul24,2018at8:36 @artyI'veprovidedananswertothiswithexamples:stackoverflow.com/a/52237988/1432509 – Alister Sep11,2018at13:20 Allsolutionsforprivateproperties/methods,ES5/ES6+,allfailtoproviderealprivacysinceChromebasedbrowserscanalwaysrevealtheentireexecutioncontextinthe[Scopes]objectofanyprototype.Somethingsjusthavetobecodedoutsidethebrowserscope.Inmytest,nomethodwillhideanythingfromChrome. – thednp Feb6,2021at13:47 Addacomment  |  41Answers 41 Sortedby: Resettodefault Highestscore(default) Datemodified(newestfirst) Datecreated(oldestfirst) 1 2 Next 313 Shortanswer,no,thereisnonativesupportforprivatepropertieswithES6classes. Butyoucouldmimicthatbehaviourbynotattachingthenewpropertiestotheobject,butkeepingtheminsideaclassconstructor,andusegettersandsetterstoreachthehiddenproperties.Notethatthegettersandsettersgetsredefineoneachnewinstanceoftheclass. ES6 classPerson{ constructor(name){ var_name=name this.setName=function(name){_name=name;} this.getName=function(){return_name;} } } ES5 functionPerson(name){ var_name=name this.setName=function(name){_name=name;} this.getName=function(){return_name;} } Share Follow editedMay11,2018at19:33 kmiklas 12k1919goldbadges5858silverbadges9494bronzebadges answeredJan27,2015at7:52 MetalGodwinMetalGodwin 3,62922goldbadges1515silverbadges1313bronzebadges 12 3 Ilikethissolutionthebest.Iagreeitshouldn'tbeusedforscalingbutit'sperfectforclassesthatwillusuallyonlybeinstantiatedonceperinclude. – BlakeRegalia Oct12,2015at20:49 2 Alsoyouareredefiningeverysinglecomponentofthisclasseachtimeanewiscreated. – QuentinRoy Nov30,2015at20:15 12 Thisissoweird!InES6youarecreatingmore"closurepyramids"thanbeforeES6!DefiningfunctionsWITHINaconstructorlooksuglierthanitdidintheaboveES5example. – Kokodoko Nov14,2016at11:24 19 Allthisdoesisintroduceindirection.NowhowdoyoumakethegetNameandsetNamepropertiesprivate? – aij Apr12,2018at16:10 2 @aijSonameonelanguagethatdoesnotdothesame.Youcaneasilyseethathecouldjustcommentoutthesetterorthegetterorbothandthat_nameistrulyprivate. – StijndeWitt Jan15,2019at22:57  |  Show7morecomments 283 PrivateclassfeaturesisinStage3proposal.Themajorityofitsfeaturesaresupportedbyallmajorbrowsers. classSomething{ #property; constructor(){ this.#property="test"; } #privateMethod(){ return'helloworld'; } getPrivateMessage(){ returnthis.#property; } } constinstance=newSomething(); console.log(instance.property);//=>undefined console.log(instance.privateMethod);//=>undefined console.log(instance.getPrivateMessage());//=>test console.log(instance.#property);//=>Syntaxerror Share Follow editedOct12,2021at15:52 TobiAkanji 2544bronzebadges answeredSep8,2018at18:02 AlisterAlister 24k88goldbadges3838silverbadges3434bronzebadges 19 7 Andwhatabouteslint?Igotparsererroratequalsign.Babelisworking,justeslintcan'tparsethisnewjssyntax. – martonx Feb4,2019at21:55 13 Wowthisisveryugly.Hashtagisavalidcharacter.Thepropertyisnotreallyprivate,or?..IcheckeditinTypeScript.Privatemembersarenotcompiledinprivateorread-only(fromoutside).Justdeclaredlikeanother(public)property.(ES5). – Dominik Feb5,2019at9:49 1 Bynow,thissolutionisalsoofficiallysupportedinGoogleChromeandNode.jsv12.Privategettersandsettersareindevelopment. – EykRehbein May10,2019at15:56 3 Howdoyouwriteprivatemethodswiththis?CanIdothis:#beep(){};andthis:async#bzzzt(){}? – КонстантинВан Jun4,2019at21:58 2 Using_wouldbeabreakingchange,unlesswhatyoumeanisthatJSdoesn'tneedprivateprivatepropertiesatall – decorator-factory Sep1,2021at21:01  |  Show14morecomments 223 Yes,prefixthenamewith#andincludeitintheclassdefinition,notjusttheconstructor. RealprivatepropertieswerefinallyaddedinES2022.Asof2022-03-22,privateproperties(fieldsandmethods)havebeensupportedinallmajorbrowsersforatleastsixmonths,but10-20%ofusersarestillonolderbrowsers[CanIUse]. Example: classPerson{ #age constructor(name){ this.name=name;//thisispublic this.#age=20;//thisisprivate } greet(){ //herewecanaccessbothnameandage console.log(`name:${this.name},age:${this.#age}`); } } letjoe=newPerson('Joe'); joe.greet(); //herewecanaccessnamebutnotage Followingaremethodsforkeepingpropertiesprivateinpre-ES2022environments,withvarioustradeoffs. Scopedvariables Theapproachhereistousethescopeoftheconstructorfunction,whichisprivate,tostoreprivatedata.Formethodstohaveaccesstothisprivatedatatheymustbecreatedwithintheconstructoraswell,meaningyou'rerecreatingthemwitheveryinstance.Thisisaperformanceandmemorypenalty,butitmaybeacceptable.Thepenaltycanbeavoidedformethodsthatdonotneedaccesstoprivatedatabydeclaringtheminthenormalway. Example: classPerson{ constructor(name){ letage=20;//thisisprivate this.name=name;//thisispublic this.greet=()=>{ //herewecanaccessbothnameandage console.log(`name:${this.name},age:${age}`); }; } anotherMethod(){ //herewecanaccessnamebutnotage } } letjoe=newPerson('Joe'); joe.greet(); //herewecanaccessnamebutnotage ScopedWeakMap AWeakMapcanbeusedtoimprovetheperformanceoftheaboveapproach,inexchangeforevenmoreclutter.WeakMapsassociatedatawithObjects(here,classinstances)insuchawaythatitcanonlybeaccessedusingthatWeakMap.So,weusethescopedvariablesmethodtocreateaprivateWeakMap,thenusethatWeakMaptoretrieveprivatedataassociatedwiththis.ThisisfasterthanthescopedvariablesmethodbecauseallyourinstancescanshareasingleWeakMap,soyoudon'tneedtorecreatemethodsjusttomakethemaccesstheirownWeakMaps. Example: letPerson=(function(){ letprivateProps=newWeakMap(); returnclassPerson{ constructor(name){ this.name=name;//thisispublic privateProps.set(this,{age:20});//thisisprivate } greet(){ //Herewecanaccessbothnameandage console.log(`name:${this.name},age:${privateProps.get(this).age}`); } }; })(); letjoe=newPerson('Joe'); joe.greet(); //herewecanaccessnamebutnotage ThisexampleusesaWeakMapwithObjectkeystouseoneWeakMapformultipleprivateproperties;youcouldalsousemultipleWeakMapsandusethemlikeprivateAge.set(this,20),orwriteasmallwrapperanduseitanotherway,likeprivateProps.set(this,'age',0). TheprivacyofthisapproachcouldtheoreticallybebreachedbytamperingwiththeglobalWeakMapobject.Thatsaid,allJavaScriptcanbebrokenbymangledglobals. (ThismethodcouldalsobedonewithMap,butWeakMapisbetterbecauseMapwillcreatememoryleaksunlessyou'reverycareful,andforthispurposethetwoaren'totherwisedifferent.) Half-Answer:ScopedSymbols ASymbolisatypeofprimitivevaluethatcanserveasapropertynameinsteadofastring.YoucanusethescopedvariablemethodtocreateaprivateSymbol,thenstoreprivatedataatthis[mySymbol]. TheprivacyofthismethodcanbebreachedusingObject.getOwnPropertySymbols,butissomewhatawkwardtodo. Example: letPerson=(()=>{ letageKey=Symbol(); returnclassPerson{ constructor(name){ this.name=name;//thisispublic this[ageKey]=20;//thisisintendedtobeprivate } greet(){ //Herewecanaccessbothnameandage console.log(`name:${this.name},age:${this[ageKey]}`); } } })(); letjoe=newPerson('Joe'); joe.greet(); //Herewecanaccessjoe'snameand,withalittleeffort,age.Wecan’t //accessageKeydirectly,butwecanobtainitbylistingallSymbol //propertieson`joe`with`Object.getOwnPropertySymbols(joe)`. Notethatmakingapropertynon-enumerableusingObject.definePropertydoesnotpreventitfrombeingincludedinObject.getOwnPropertySymbols. Half-Answer:Underscores Theoldconventionistojustuseapublicpropertywithanunderscoreprefix.Thisdoesnotkeepitprivate,butitdoesdoagoodjobofcommunicatingtoreadersthattheyshouldtreatitasprivate,whichoftengetsthejobdone.Inexchangeforthis,wegetanapproachthat'seasiertoread,easiertotype,andfasterthantheotherworkarounds. Example: classPerson{ constructor(name){ this.name=name;//thisispublic this._age=20;//thisisintendedtobeprivate } greet(){ //Herewecanaccessbothnameandage console.log(`name:${this.name},age:${this._age}`); } } letjoe=newPerson('Joe'); joe.greet(); //Herewecanaccessbothjoe'snameandage.Butweknowwearen't //supposedtoaccesshisage,whichjustmightstopus. Summary ES2022:greatbutnotyetsupportedbyallvisitors Scopedvariables:private,slower,awkward ScopedWeakMaps:hackable,awkward ScopedSymbols:enumerableandhackable,somewhatawkward Underscores:justarequestforprivacy,nootherdownsides Share Follow edited12hoursago answeredNov4,2015at22:52 twhbtwhb 3,70422goldbadges1818silverbadges2222bronzebadges 13 8 Thefirstexamplesnippet("scopedvariables")isatotalantipattern-eachreturnedobjectwillhaveadifferentclass.Don'tdothat.Ifyouwantprivilegedmethods,createthemintheconstructor. – Bergi Nov5,2015at0:35 1 Wrappingaclassinsideafunctionseemstodefeatthewholepurposeofusingclassesinthefirstplace.Ifyoualreadyusethefunctiontocreateaninstance,youmightaswellplaceallyourprivate/publicmembersinsidethatfunctionaswell,andforgetaboutthewholeclasskeyword. – Kokodoko Dec22,2015at13:59 2 @Bergi@KokodokoIeditedthescopedvariablesapproachtobeslightlyfasterandnotbreakinstanceof.IadmitIwasthinkingofthatapproachasincludedonlyforcompleteness'sakeandshouldhavegivenmorethoughttohowmuchitisactuallycapableof. – twhb Dec23,2015at17:50 2 Excellentexplanation!I'mstillsurprisedthatES6actuallymadeithardertosimulateaprivatevariable,whereinES5youcouldjustusevarandthisinsideafunctiontosimulateprivateandpublic. – Kokodoko Nov14,2016at11:29 2 @KokodokoIfyoudispensewiththeclassandjustputeverythinginthefunction,youwillalsohavetoreverttoimplementinginheritanceusingtheprototypemethod.Usingextendonclassesisbyfaracleanerapproach,sousingaclassinsideafunctionistotallyacceptable. – Johann May24,2017at6:47  |  Show8morecomments 123 Update:Aproposalwithnicersyntaxisonitsway.Contributionsarewelcome. Yes,thereis-forscopedaccessinobjects-ES6introducesSymbols. Symbolsareunique,youcan'tgainaccesstoonefromtheoutsideexceptwithreflection(likeprivatesinJava/C#)butanyonewhohasaccesstoasymbolontheinsidecanuseitforkeyaccess: varproperty=Symbol(); classSomething{ constructor(){ this[property]="test"; } } varinstance=newSomething(); console.log(instance.property);//=>undefined,canonlyaccesswithaccesstotheSymbol Share Follow editedOct6,2020at3:29 Mahmoud 8811silverbadge77bronzebadges answeredMar3,2014at23:51 BenjaminGruenbaumBenjaminGruenbaum 258k8282goldbadges485485silverbadges485485bronzebadges 19 7 Can'tyouuseObject.getOwnPropertySymbols?;) – Qantas94Heavy Mar4,2014at5:16 42 @BenjaminGruenbaum:ApparentlySymbolsnolongerensuretrueprivacy:stackoverflow.com/a/22280202/1282216 – d13 Mar19,2014at14:39 32 @trusktrthroughthrekeys?No.Throughthesymbols?Yes.VerymuchlikehowyoucanusereflectioninlanguageslikeC#andJavatoaccessprivatefields.Accessmodifiersaren'taboutsecurity-they'reaboutclarityofintent. – BenjaminGruenbaum Oct26,2014at7:20 10 ItseemslikeusingSymbolsissimilartodoingconstmyPrivateMethod=Math.random();Something.prototype[''+myPrivateMethod]=function(){...}newSomething()[''+myPrivateMethod]();.Thisisn'treallyprivacy,it'sobscurity,inthesenseoftraditionalJavaScript.Iwouldconsider"private"JavaScripttomeanusingclosurestoencapsulatevariables.Thosevariablesarehencenotaccessiblethroughreflection. – trusktr Oct26,2014at8:54 13 Also,IfeelthatusingtheprivateandprotectedkeywordswouldbesomuchcleanerthanSymbolorName.Ipreferdotnotationratherthanbracketnotation.I'dliketokeepusingadotforprivatethings.this.privateVar – trusktr Oct26,2014at8:54  |  Show14morecomments 35 Theansweris"No".Butyoucancreateprivateaccesstopropertieslikethis: Usemodules.Everythinginamoduleisprivateunlessit'smadepublicbyusingtheexportkeyword. Insidemodules,usefunctionclosure:http://www.kirupa.com/html5/closures_in_javascript.htm (ThesuggestionthatSymbolscouldbeusedtoensureprivacywastrueinanearlierversionoftheES6specbutisnolongerthecase:https://mail.mozilla.org/pipermail/es-discuss/2014-January/035604.htmlandhttps://stackoverflow.com/a/22280202/1282216.ForalongerdiscussionaboutSymbolsandprivacysee:https://curiosity-driven.org/private-properties-in-javascript) Share Follow editedMay23,2017at12:18 CommunityBot 111silverbadge answeredMar19,2014at14:43 d13d13 10.1k1212goldbadges3535silverbadges3939bronzebadges 4 6 -1,thisdoesnotansweryourquestionreally.(YoucanuseclosureswithIIFEsinES5too).Privatepropertiesareenumerablethroughreflectioninmostlanguages(Java,C#,etc).Thepointofprivatepropertiesistoconveyintenttootherprogrmamersandnottoenforcesecurity. – BenjaminGruenbaum Mar19,2014at20:19 1 @BenjaminGruenbaum,Iknow,IwishIhadabetteranswer,I'mnothappywithiteither. – d13 Mar20,2014at1:42 Ithinksymbolsarestillavalidwaytoachieveinaccessiblememberswhileintheprogrammingenvironment.Yes,theycanstillbefoundifyoureallllyyywant,butthat'snotthepointisit?Youshouldn'tstoresensitiveinformationinit,butyoushouldn'tdothatanywayinclient-sidecode.Butitworksforthepurposeofhidingapropertyormethodfromanoutsideclass. – Kokodoko May24,2017at9:11 1 Usingvariablesscopedatthelevelofamoduleassubstituteforprivatepropertiesinaclasswillleadtoasingleton.behaviororbehaviorsimilarttostatitcproperties.Instancesofvarswillgetshared. – AdrianMoisa Dec24,2017at8:40 Addacomment  |  30 TheonlywaytogettrueprivacyinJSisthroughscoping,sothereisnowaytohaveapropertythatisamemberofthisthatwillbeaccessibleonlyinsidethecomponent.ThebestwaytostoretrulyprivatedatainES6iswithaWeakMap. constprivateProp1=newWeakMap(); constprivateProp2=newWeakMap(); classSomeClass{ constructor(){ privateProp1.set(this,"IamPrivate1"); privateProp2.set(this,"IamPrivate2"); this.publicVar="Iampublic"; this.publicMethod=()=>{ console.log(privateProp1.get(this),privateProp2.get(this)) }; } printPrivate(){ console.log(privateProp1.get(this)); } } Obviouslythisisaprobablyslow,anddefinitelyugly,butitdoesprovideprivacy. KeepinmindthatEVENTHISisn'tperfect,becauseJavascriptissodynamic.Someonecouldstilldo varoldSet=WeakMap.prototype.set; WeakMap.prototype.set=function(key,value){ //Store'this','key',and'value' returnoldSet.call(this,key,value); }; tocatchvaluesastheyarestored,soifyouwantedtobeextracareful,you'dneedtocapturealocalreferenceto.setand.gettouseexplicitlyinsteadofrelyingontheoverridableprototype. const{set:WMSet,get:WMGet}=WeakMap.prototype; constprivateProp1=newWeakMap(); constprivateProp2=newWeakMap(); classSomeClass{ constructor(){ WMSet.call(privateProp1,this,"IamPrivate1"); WMSet.call(privateProp2,this,"IamPrivate2"); this.publicVar="Iampublic"; this.publicMethod=()=>{ console.log(WMGet.call(privateProp1,this),WMGet.call(privateProp2,this)) }; } printPrivate(){ console.log(WMGet.call(privateProp1,this)); } } Share Follow editedJan3,2016at22:25 answeredJul21,2015at23:54 loganfsmythloganfsmyth 145k2727goldbadges312312silverbadges239239bronzebadges 4 3 Asasuggestion,youcanavoidusingoneweakmapperpropertybyusinganobjectasvalue.Thiswayyoucanalsoreducethenumberofmap'sgettoonepermethod(e.g.const_=privates.get(this);console.log(_.privateProp1);). – QuentinRoy Nov30,2015at20:21 Yup,that'stotallyanoptiontoo.Imostlywentwiththissinceitmapsmoredirectlytowhatauserwouldhavewrittenwhenusingrealproperties. – loganfsmyth Nov30,2015at21:01 @loganfsmythconstmyObj=newSomeClass();console.log(privateProp1.get(myObj))//"IamPrivate1"thatmeansthatyourpropertyisprivateornot? – stackoverflow May26,2017at12:04 2 Forthattowork,thecodeaccessingthepropertywouldneedaccesstotheWeakMapobject,whichwouldnormallybescopedinsideofamoduleandinaccessible – loganfsmyth May26,2017at14:05 Addacomment  |  22 Forfuturereferenceofotheronlookers,I'mhearingnowthattherecommendationistouseWeakMapstoholdprivatedata. Hereisamoreclear,workingexample: functionstorePrivateProperties(a,b,c,d){ letprivateData=newWeakMap; //uniqueobjectaskey,weakmapcanonlyacceptobjectaskey,whenkeyisnolongerreferened,garbagecollectorclaimsthekey-value letkeyA={},keyB={},keyC={},keyD={}; privateData.set(keyA,a); privateData.set(keyB,b); privateData.set(keyC,c); privateData.set(keyD,d); return{ logPrivateKey(key){ switch(key){ case"a": console.log(privateData.get(keyA)); break; case"b": console.log(privateData.get(keyB)); break; case"c": console.log(privateData.get(keyC)); break; case"d": console.log(privateData.set(keyD)); break; default: console.log(`Thereisnovaluefor${key}`) } } } } Share Follow editedMay23,2017at12:34 CommunityBot 111silverbadge answeredJan14,2015at0:09 user1076821user1076821 9 20 Beawarethatthesepropertiesarestatic. – MichaelTheriot Jan26,2015at23:35 8 Ididn'tdownvoteyoubutyourweakmapexampleiscompletelywrong. – BenjaminGruenbaum Apr2,2015at21:51 4 Namely-You'resharingthedatabetweenallclassinstancesandnotperinstance-mayIatleastfixit? – BenjaminGruenbaum Apr4,2015at13:25 1 Indeed,theweakmapneedstobeattachedtoagiveninstance.Seefitzgeraldnick.com/weblog/53foranexample. – widged Jul6,2015at3:16 2 AccordingtoMDN,primitivedatatypessuchasSymbolsarenotallowedasaWeakMapkey.MDNWeakMapDocumentation – leepowell Sep30,2015at9:27  |  Show4morecomments 12 Dependsonwhomyouask:-) NoprivatepropertymodifierisincludedintheMaximallyminimalclassesproposalwhichseemstohavemadeitintothecurrentdraft. However,theremightbesupportforprivatenames,whichdoesallowprivateproperties-andtheyprobablycouldbeusedinclassdefinitionsaswell. Share Follow answeredMar3,2014at22:20 BergiBergi 561k125125goldbadges886886silverbadges12551255bronzebadges 12 3 It'shighlyunlikelythatprivatenameswillmakeitintoES6,thoughthey'rethinkingofsomeformofprivatethingforES7. – Qantas94Heavy Mar4,2014at5:16 @Qantas94HeavybothprivatenamesanduniquestringvalueshavebeensupersededbySymbolsfromwhatIunderstand. – BenjaminGruenbaum Mar4,2014at5:43 Yeah,itprobablywillbecomeSymbols.However,afaikthe"symbols"currentlycontainedinthespecareonlyusedtodescribeinternalpropertieslike[[prototype]],andthereisnowaytocreateandusetheminusercode.Doyouknowsomedocs? – Bergi Mar4,2014at13:19 Ijustrealizedthatmodulescanbeusedtosetprivacy.CombinedwithSymbolsthatmightbeallyou'deverneed...? – d13 Mar5,2014at1:18 1 @Cody:YourwholemodulecodedoeshaveitsownscopeinES6anyway,noneedforanIEFE.Andyes,symbolsarepurposedforuniqueness(collision-avoidance),notprivacy. – Bergi Sep4,2015at21:52  |  Show7morecomments 10 UsingES6modules(initiallyproposedby@d13)workswellforme.Itdoesn'tmimicprivatepropertiesperfectly,butatleastyoucanbeconfidentthatpropertiesthatshouldbeprivatewon'tleakoutsideofyourclass.Here'sanexample: something.js let_message=null; const_greet=name=>{ console.log('Hello'+name); }; exportdefaultclassSomething{ constructor(message){ _message=message; } say(){ console.log(_message); _greet('Bob'); } }; Thentheconsumingcodecanlooklikethis: importSomethingfrom'./something.js'; constsomething=newSomething('Sunnyday!'); something.say(); something._message;//undefined something._greet();//exception Update(Important): As@DanyalAytekinoutlinedinthecomments,theseprivatepropertiesarestatic,sothereforeglobalinscope.TheywillworkwellwhenworkingwithSingletons,butcaremustbetakenforTransientobjects.Extendingtheexampleabove: importSomethingfrom'./something.js'; importSomething2from'./something.js'; consta=newSomething('a'); a.say();//a constb=newSomething('b'); b.say();//b constc=newSomething2('c'); c.say();//c a.say();//c b.say();//c c.say();//c Share Follow editedMar27,2018at0:24 answeredMar14,2016at13:10 JohnnyOshikaJohnnyOshika 49.3k3737goldbadges162162silverbadges253253bronzebadges 6 4 Goodforprivatestatic. – DanyalAytekin Mar23,2016at15:05 @DanyalAytekin:that'saverygoodpoint.Theseprivatepropertiesarestaticsoglobalinscope.I'veupdatedmyanswertoreflectthis. – JohnnyOshika Mar26,2016at19:06 ThemoreIlearnaboutfunctionalprogramming(especiallyElmandHaskell)themoreIbelievethatJSprogrammerswouldbenefitfromamodule-basedapproachto"modularity"ratherthananOOPclass-basedone.IfwethinkofES6modulesasthefoundationsforbuildingapplications,andforgetaboutclassesentirely,Ibelievewemayendupwithmuchbetterapplicationsoverall.CouldanyexperiencedElmorHaskelluserscommentonthisapproach? – d13 Apr9,2016at22:04 1 Intheupdate,theseconda.say();//ashouldbeb.say();//b – grokky Oct2,2017at8:04 triedlet_message=nullway,notsocool,whencallconstructormultipletimes,itmessup. – Littlee Mar30,2018at13:35  |  Show1morecomment 9 Yes-youcancreateencapsulatedproperty,butit'snotbeendonewithaccessmodifiers(public|private)atleastnotwithES6. HereisasimpleexamplehowitcanbedonewithES6: 1Createclassusingclassword 2Insideit'sconstructordeclareblock-scopedvariableusingletORconstreservedwords->sincetheyareblock-scopetheycannotbeaccessedfromoutside(encapsulated) 3Toallowsomeaccesscontrol(setters|getters)tothosevariablesyoucandeclareinstancemethodinsideit'sconstructorusing:this.methodName=function(){}syntax "usestrict"; classSomething{ constructor(){ //privateproperty letproperty="test"; //privatefinal(immutable)property constproperty2="test2"; //publicgetter this.getProperty2=function(){ returnproperty2; } //publicgetter this.getProperty=function(){ returnproperty; } //publicsetter this.setProperty=function(prop){ property=prop; } } } Nowletscheckit: vars=newSomething(); console.log(typeofs.property);//undefined s.setProperty("another");//settoencapsulated`property` console.log(s.getProperty());//getencapsulated`property`value console.log(s.getProperty2());//getencapsulatedimmutable`property2`value Share Follow answeredFeb8,2016at15:28 NikitaKurtinNikitaKurtin 5,17933goldbadges4242silverbadges4646bronzebadges 6 1 Thisis(fornow)theonlyonesolutiontothisproblemdespitethefactthatallmethodsdeclaredintheconstructorareredeclaredforeachinstanceoftheclass.Thisisprettyabadidearegardingperformanceandmemoryusage.Classmethodsshouldbedeclaredoutsideoftheconstructorscope. – Freezystem Feb10,2016at22:23 @FreezystemFirst:Firstthoseareinstancemethods(notClassmethods).SecondOPquestionwas:_HowcanIpreventaccesstoinstance.property?_andmyansweris:anexampleofhow...Thirdifyouhaveanybetteridea-let'shearit – NikitaKurtin Feb11,2016at9:49 1 Iwasnotsayingyouwerewrong,IsaidthatyoursolutionwasthebestcompromisetoachieveprivatevariabledespitethefactthatacopyofeachinstancemethodsiscreatedeachtimeyoucallnewSomething();becauseyourmethodsaredeclaredintheconstructortohaveaccesstotheseprivatevariables.Thatmaycausealotofmemoryconsumptionifyoucreatealotofinstanceofyourclass,soperformanceissues.Methodsshouldhavebeendeclaredoutsideofconstructorscope.Mycommentwasmoreanexplanationofyoursolutiondrawbacksthanacriticism. – Freezystem Feb11,2016at10:28 1 Butisn'titbadpracticedodefineyourentireclassinsidetheconstructor?Aren'twejust"hacking"javascriptnow?JustlookatanyotherOOPprogramminglanguage,andyou'llseethattheconstructorisnotmeanttodefineaclass. – Kokodoko Nov14,2016at11:26 1 Yesthat'swhatImeant,andyoursolutionworks!I'mjustsayingthatingeneralIamsurprisedthatES6addeda'class'keyword,butremovedtheelegantsolutionofworkingwithvarandthis,toachieveencapsulation. – Kokodoko Nov15,2016at10:54  |  Show1morecomment 9 Completing@d13andthecommentsby@johnny-oshikaand@DanyalAytekin: Iguessintheexampleprovidedby@johnny-oshikawecouldusenormalfunctionsinsteadofarrowfunctionsandthen.bindthemwiththecurrentobjectplusa_privatesobjectasacurriedparameter: something.js function_greet(_privates){ return'Hello'+_privates.message; } function_updateMessage(_privates,newMessage){ _privates.message=newMessage; } exportdefaultclassSomething{ constructor(message){ const_privates={ message }; this.say=_greet.bind(this,_privates); this.updateMessage=_updateMessage.bind(this,_privates); } } main.js importSomethingfrom'./something.js'; constsomething=newSomething('Sunnyday!'); constmessage1=something.say(); something.updateMessage('Cloudyday!'); constmessage2=something.say(); console.log(message1==='HelloSunnyday!');//true console.log(message2==='HelloCloudyday!');//true //thefollowingsarenotpublic console.log(something._greet===undefined);//true console.log(something._privates===undefined);//true console.log(something._updateMessage===undefined);//true //anotherinstancewhichdoesn'tsharethe_privates constsomething2=newSomething('anotherSunnyday!'); constmessage3=something2.say(); console.log(message3==='HelloanotherSunnyday!');//true BenefitsIcanthinkof: wecanhaveprivatemethods(_greetand_updateMessageactlikeprivatemethodsaslongaswedon'texportthereferences) althoughthey'renotontheprototype,theabovementionedmethodswillsavememorybecausetheinstancesarecreatedonce,outsidetheclass(asopposedtodefiningthemintheconstructor) wedon'tleakanyglobalssincewe'reinsideamodule wecanalsohaveprivatepropertiesusingthebinded_privatesobject SomedrawbacksIcanthinkof: lessintuitive mixedusageofclasssyntaxandoldschoolpatterns(objectbindings,module/functionscopedvariables) hardbindings-wecan'trebindthepublicmethods(althoughwecanimprovethisbyusingsoftbindings(https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#softening-binding)) Arunningsnippetcanbefoundhere:http://www.webpackbin.com/NJgI5J8lZ Share Follow editedApr24,2016at18:04 answeredApr24,2016at17:54 efidilesefidiles 18122silverbadges22bronzebadges Addacomment  |  7 Adifferentapproachto"private" InsteadoffightingagainstthefactthatprivatevisibilityiscurrentlyunavailableinES6,IdecidedtotakeamorepracticalapproachthatdoesjustfineifyourIDEsupportsJSDoc(e.g.,Webstorm)[email protected],theIDEwillpreventyoufromaccessinganyprivatememberfromoutsideitsclass.Worksprettywellformeandit'sbeenreallyusefulforhidinginternalmethodssotheauto-completefeatureshowsmejustwhattheclassreallymeanttoexpose.Here'sanexample: Share Follow answeredOct1,2017at20:27 LucioPaivaLucioPaiva 15.6k77goldbadges7777silverbadges9696bronzebadges 2 3 Theproblemis,thatwedon'twan'ttoaccesstheprivatevariablesovertheEditor,wewan'ttoprotecttheprivatevariablesfromoutside-Andthatis,whatpublic/privatedoes.Ifyourcodeisfinished,youcanaccess(andtheimportantthinks:override)thesevariablesfromoutsidetheclass.Your@privatecommentcannotpreventthese,it'sonlyaFeaturefordocumentation-generationandyou'rIDE. – AdrianPreuss Apr21,2018at17:42 Yes,Iamawareofthat.It'sjustthatthat'senoughformeandmaybeenoughforotherpeopleoutthere.Iknowit'snotreallymakingmyvariablesprivate;it'sonlywarningmenottotryandaccessitfromoutside(only,ofcourse,ifmyteamandIareallusinganIDEthatsupportsthisfeature).Javascript(andotherlanguages,likePython)wasnotdesignedwithaccesslevelsinmind.Peopledoallsortsofstufftosomehowimplementthatfunctionality,butintheendweendupjusthackingthelanguagetoachievethat.Idecidedtogowithamore"natural"approach,ifyouwill. – LucioPaiva Apr21,2018at18:19 Addacomment  |  7 Oh,somanyexoticsolutions!Iusuallydon'tcareaboutprivacysoIuse"pseudoprivacy"asit'ssaidhere.Butifdocare(iftherearesomespecialrequirementsforthat)Iusesomethinglikeinthisexample: classjobImpl{ //public constructor(name){ this.name=name; } //public do(time){ console.log(`${this.name}startedat${time}`); this.prepare(); this.execute(); } //public stop(time){ this.finish(); console.log(`${this.name}finishedat${time}`); } //private prepare(){console.log('prepare..');} //private execute(){console.log('execute..');} //private finish(){console.log('finish..');} } functionJob(name){ varimpl=newjobImpl(name); return{ do:time=>impl.do(time), stop:time=>impl.stop(time) }; } //Test: //createclass"Job" varj=newJob("Diggingaditch"); //callpublicmembers.. j.do("08:00am"); j.stop("06:00pm"); //trytocallprivatemembersorfields.. console.log(j.name);//undefined j.execute();//error Anotherpossibleimplementationoffunction(constructor)Job: functionJob(name){ varimpl=newjobImpl(name); this.do=time=>impl.do(time), this.stop=time=>impl.stop(time) } Share Follow editedNov10,2018at8:02 answeredOct28,2018at13:56 SergeiSergei 5,35544goldbadges3434silverbadges4949bronzebadges Addacomment  |  6 WeakMap supportedinIE11(Symbolsarenot) hard-private(propsusingSymbolsaresoft-privateduetoObject.getOwnPropertySymbols) canlookreallyclean(unlikeclosureswhichrequireallpropsandmethodsintheconstructor) First,defineafunctiontowrapWeakMap: functionPrivate(){ constmap=newWeakMap(); returnobj=>{ letprops=map.get(obj); if(!props){ props={}; map.set(obj,props); } returnprops; }; } Then,constructareferenceoutsideyourclass: constp=newPrivate(); classPerson{ constructor(name,age){ this.name=name; p(this).age=age;//it'seasytosetaprivatevariable } getAge(){ returnp(this).age;//andgetaprivatevariable } } Note:classisn'tsupportedbyIE11,butitlookscleanerintheexample. Share Follow editedNov27,2017at1:24 answeredAug3,2017at23:42 kevlenedkevlened 10k44goldbadges2121silverbadges1616bronzebadges Addacomment  |  6 Icameacrossthispostwhenlookingforthebestpracticefor"privatedataforclasses".Itwasmentionedthatafewofthepatternswouldhaveperformanceissues. Iputtogetherafewjsperftestsbasedonthe4mainpatternsfromtheonlinebook"ExploringES6": http://exploringjs.com/es6/ch_classes.html#sec_private-data-for-classes Thetestscanbefoundhere: https://jsperf.com/private-data-for-classes InChrome63.0.3239/MacOSX10.11.6,thebestperformingpatternswere"Privatedataviaconstructorenvironments"and"Privatedataviaanamingconvention".FormeSafariperformedwellforWeakMapbutChromenotsowell. Idon'tknowthememoryimpact,butthepatternfor"constructorenvironments"whichsomehadwarnedwouldbeaperformanceissuewasveryperformant. The4basicpatternsare: Privatedataviaconstructorenvironments classCountdown{ constructor(counter,action){ Object.assign(this,{ dec(){ if(counter<1)return; counter--; if(counter===0){ action(); } } }); } } constc=newCountdown(2,()=>{}); c.dec(); c.dec(); Privatedataviaconstructorenvironments2 classCountdown{ constructor(counter,action){ this.dec=functiondec(){ if(counter<1)return; counter--; if(counter===0){ action(); } } } } constc=newCountdown(2,()=>{}); c.dec(); c.dec(); Privatedataviaanamingconvention classCountdown{ constructor(counter,action){ this._counter=counter; this._action=action; } dec(){ if(this._counter<1)return; this._counter--; if(this._counter===0){ this._action(); } } } constc=newCountdown(2,()=>{}); c.dec(); c.dec(); PrivatedataviaWeakMaps const_counter=newWeakMap(); const_action=newWeakMap(); classCountdown{ constructor(counter,action){ _counter.set(this,counter); _action.set(this,action); } dec(){ letcounter=_counter.get(this); if(counter<1)return; counter--; _counter.set(this,counter); if(counter===0){ _action.get(this)(); } } } constc=newCountdown(2,()=>{}); c.dec(); c.dec(); Privatedataviasymbols const_counter=Symbol('counter'); const_action=Symbol('action'); classCountdown{ constructor(counter,action){ this[_counter]=counter; this[_action]=action; } dec(){ if(this[_counter]<1)return; this[_counter]--; if(this[_counter]===0){ this[_action](); } } } constc=newCountdown(2,()=>{}); c.dec(); c.dec(); Share Follow answeredJan8,2018at23:48 MarkMMarkM 10111silverbadge33bronzebadges Addacomment  |  5 PersonallyIliketheproposalofthebindoperator::andwouldthencombineitwiththesolution@d13mentionedbutfornowstickwith@d13'sanswerwhereyouusetheexportkeywordforyourclassandputtheprivatefunctionsinthemodule. thereisonemoresolutiontoughwhichhasn'tbeenmentionedherethatfollowsaremorefunctionalapproachandwouldallowittohavealltheprivateprops/methodswithintheclass. Private.js exportconstget=state=>key=>state[key]; exportconstset=state=>(key,value)=>{state[key]=value;} Test.js import{get,set}from'./utils/Private' exportdefaultclassTest{ constructor(initialState={}){ const_set=this.set=set(initialState); const_get=this.get=get(initialState); this.set('privateMethod',()=>_get('propValue')); } showProp(){ returnthis.get('privateMethod')(); } } letone=newTest({propValue:5}); lettwo=newTest({propValue:8}); two.showProp();//8 one.showProp();//5 commentsonitwouldbeappreciated. Share Follow answeredApr9,2017at18:24 RobinF.RobinF. 9771010silverbadges1717bronzebadges 1 GenerallyIliketheapproach.Feedback:1.youwillneedadifferentprivate.jsmoduleforeachclasstopreventclashing.2.Idislikethepotentialofmakingtheconstructorreallylongbyinline-definingeachofyourprivatemethods.3.Itwouldbeniceifalloftheclassmethodswereinonefile. – DougCoburn Jun16,2017at19:28 Addacomment  |  5 IthinkBenjamin'sanswerisprobablythebestformostcasesuntilthelanguagenativelysupportsexplicitlyprivatevariables. However,ifforsomereasonyouneedtopreventaccesswithObject.getOwnPropertySymbols(),amethodI'veconsideredusingisattachingaunique,non-configurable,non-enumerable,non-writablepropertythatcanbeusedasapropertyidentifiertoeachobjectonconstruction(suchasauniqueSymbol,ifyoudon'talreadyhavesomeotheruniquepropertylikeanid).Thenjustkeepamapofeachobject's'private'variablesusingthatidentifier. constprivateVars={}; classSomething{ constructor(){ Object.defineProperty(this,'_sym',{ configurable:false, enumerable:false, writable:false, value:Symbol() }); varmyPrivateVars={ privateProperty:"I'mhidden" }; privateVars[this._sym]=myPrivateVars; this.property="I'mpublic"; } getPrivateProperty(){ returnprivateVars[this._sym].privateProperty; } //Acleanupmethodofsomekindisnecessarysincethe //variableswon'tbecleanedupfrommemoryautomatically //whentheobjectisgarbagecollected destroy(){ deleteprivateVars[this._sym]; } } varinstance=newSomething(); console.log(instance.property);//=>"I'mpublic" console.log(instance.privateProperty);//=>undefined console.log(instance.getPrivateProperty());//=>"I'mhidden" ThepotentialadvantageofthisapproachoverusingaWeakMapisfasteraccesstimeifperformancebecomesaconcern. Share Follow editedDec29,2017at12:29 answeredAug8,2016at21:06 NanoWizardNanoWizard 1,94911goldbadge1919silverbadges3333bronzebadges 2 2 CorrectmeifIamwrong,butwouldn'tthiscodecontainmemoryleakssinceprivateVarswillstillstoreanobject'sprivatevariableseveniftheobjectisalreadydestroyed? – RussellSantos Dec28,2017at5:47 @RussellSantosyouarecorrect,assumingtheobjectswillneedtobegarbagecollectedatsomepoint.Thankyouforpointingthatout.InmyexampleI'veaddedadestroy()methodwhichshouldbecalledbytheusingcodewheneveranobjectneedstoberemoved. – NanoWizard Dec29,2017at12:33 Addacomment  |  4 Ibelieveitispossibletoget'bestofbothworlds'usingclosuresinsideconstructors.Therearetwovariations: Alldatamembersareprivate functionmyFunc(){ console.log('Valueofx:'+this.x); this.myPrivateFunc(); } functionmyPrivateFunc(){ console.log('Enhancedvalueofx:'+(this.x+1)); } classTest{ constructor(){ letinternal={ x:2, }; internal.myPrivateFunc=myPrivateFunc.bind(internal); this.myFunc=myFunc.bind(internal); } }; Somemembersareprivate NOTE:Thisisadmittedlyugly.Ifyouknowabettersolution,pleaseeditthisresponse. functionmyFunc(priv,pub){ pub.y=3;//TheTestobjectnowgetsamember'y'withvalue3. console.log('Valueofx:'+priv.x); this.myPrivateFunc(); } functionmyPrivateFunc(){ pub.z=5;//TheTestobjectnowgetsamember'z'withvalue3. console.log('Enhancedvalueofx:'+(priv.x+1)); } classTest{ constructor(){ letself=this; letinternal={ x:2, }; internal.myPrivateFunc=myPrivateFunc.bind(null,internal,self); this.myFunc=myFunc.bind(null,internal,self); } }; Share Follow answeredSep20,2016at16:09 JSInitiateJSInitiate 4111bronzebadge Addacomment  |  4 InfactitispossibleusingSymbolsandProxies.Youusethesymbolsintheclassscopeandsettwotrapsinaproxy:onefortheclassprototypesothattheReflect.ownKeys(instance)orObject.getOwnPropertySymbolsdoesn'tgiveyoursymbolsaway,theotheroneisfortheconstructoritselfsowhennewClassName(attrs)iscalled,theinstancereturnedwillbeinterceptedandhavetheownpropertiessymbolsblocked. Here'sthecode: constHuman=(function(){ constpet=Symbol(); constgreet=Symbol(); constHuman=privatizeSymbolsInFn(function(name){ this.name=name;//public this[pet]='dog';//private }); Human.prototype=privatizeSymbolsInObj({ [greet](){//private return'Hithere!'; }, revealSecrets(){ console.log(this[greet]()+`Thepetisa${this[pet]}`); } }); returnHuman; })(); constbob=newHuman('Bob'); console.assert(bobinstanceofHuman); console.assert(Reflect.ownKeys(bob).length===1)//only['name'] console.assert(Reflect.ownKeys(Human.prototype).length===1)//only['revealSecrets'] //Settingupthetrapsinsideproxies: functionprivatizeSymbolsInObj(target){ returnnewProxy(target,{ownKeys:Object.getOwnPropertyNames}); } functionprivatizeSymbolsInFn(Class){ functionconstruct(TargetClass,argsList){ constinstance=newTargetClass(...argsList); returnprivatizeSymbolsInObj(instance); } returnnewProxy(Class,{construct}); } Reflect.ownKeys()workslikeso:Object.getOwnPropertyNames(myObj).concat(Object.getOwnPropertySymbols(myObj))that'swhyweneedatrapfortheseobjects. Share Follow answeredFeb27,2017at23:12 FranciscoNetoFranciscoNeto 33933silverbadges33bronzebadges 0 Addacomment  |  4 EvenTypescriptcan'tdoit.Fromtheirdocumentation: Whenamemberismarkedprivate,itcannotbeaccessedfromoutsideofitscontainingclass.Forexample: classAnimal{ privatename:string; constructor(theName:string){this.name=theName;} } newAnimal("Cat").name;//Error:'name'isprivate; Buttranspiledontheirplaygroundthisgives: varAnimal=(function(){ functionAnimal(theName){ this.name=theName; } returnAnimal; }()); console.log(newAnimal("Cat").name); Sotheir"private"keywordisineffective. Share Follow answeredApr18,2017at21:16 MichaelFranzlMichaelFranzl 1,2441313silverbadges1919bronzebadges 3 2 Well,it'sstilleffectivebecauseitprevents"bad"programming,whileintheIDE.Itshowsyouwhichmembersyoushouldandshouldn'tuse.Ithinkthat'sthemainreasonforusingprivateandpublic.(Forexample,whenyoucompileC#tomachinecode,willprivatestillbeprivate?whoknows?).Whenreadingtheotheranswers,itseemsthatusing@Symbolcanalsomakeamemberinaccessible.ButevenSymbolscanstillbefoundfromtheconsole. – Kokodoko May24,2017at9:02 DoestheTypeScripterroroccurduringthetranspileofTypeScripttoJavaScript?(Likethetypecheckinghappensattranspitetime.Ratherthansomeruntimeprivatemechanism.) – Eljay May13,2018at11:11 NotethatthisresponsetalksaboutTypeScriptspecificprivatemodifier,butTypeScript4.3introducedadditionalsupportforECMAScript#privateClassElementsthatunlikeprivatemodifierisn'tjustprivateatcompile-time,butalsoatruntime(ifcompiledto>=ES2015).IcreatedsamplecodeinTypeScriptplayfeildtodemonstrate,thatitistrulyprivate(ESNexttargetworkswithChrome,thathasimplementedsupportforESprivatefieldsproposal) – atsu85 Apr4,2021at11:04 Addacomment  |  4 ComingverylatetothispartybutIhittheOPquestioninasearchso... Yes,youcanhaveprivatepropertiesbywrappingtheclassdeclarationinaclosure ThereisanexampleofhowIhaveprivatemethodsinthiscodepen.Inthesnippetbelow,theSubscribableclasshastwo'private'functionsprocessandprocessCallbacks.Anypropertiescanbeaddedinthismannerandtheyarekeptprivatethroughtheuseoftheclosure.IMOPrivacyisarareneedifconcernsarewellseparatedandJavascriptdoesnotneedtobecomebloatedbyaddingmoresyntaxwhenaclosureneatlydoesthejob. constSubscribable=(function(){ constprocess=(self,eventName,args)=>{ self.processing.set(eventName,setTimeout(()=>processCallbacks(self,eventName,args)))}; constprocessCallbacks=(self,eventName,args)=>{ if(self.callingBack.get(eventName).length>0){ const[nextCallback,...callingBack]=self.callingBack.get(eventName); self.callingBack.set(eventName,callingBack); process(self,eventName,args); nextCallback(...args)} else{ deleteself.processing.delete(eventName)}}; returnclass{ constructor(){ this.callingBack=newMap(); this.processing=newMap(); this.toCallbacks=newMap()} subscribe(eventName,callback){ constcallbacks=this.unsubscribe(eventName,callback); this.toCallbacks.set(eventName,[...callbacks,callback]); return()=>this.unsubscribe(eventName,callback)}//callabletounsubscribeforconvenience unsubscribe(eventName,callback){ letcallbacks=this.toCallbacks.get(eventName)||[]; callbacks=callbacks.filter(subscribedCallback=>subscribedCallback!==callback); if(callbacks.length>0){ this.toCallbacks.set(eventName,callbacks)} else{ this.toCallbacks.delete(eventName)} returncallbacks} emit(eventName,...args){ this.callingBack.set(eventName,this.toCallbacks.get(eventName)||[]); if(!this.processing.has(eventName)){ process(this,eventName,args)}}}})(); Ilikethisapproachbecauseitseparatesconcernsnicelyandkeepsthingstrulyprivate.Theonlydownsideistheneedtouse'self'(orsomethingsimilar)toreferto'this'intheprivatecontent. Share Follow answeredSep7,2017at5:45 PaulWhippPaulWhipp 14.7k44goldbadges3939silverbadges5151bronzebadges 0 Addacomment  |  4 Yestotallycan,andprettyeasilytoo.Thisisdonebyexposingyourprivatevariablesandfunctionsbyreturningtheprototypeobjectgraphintheconstructor.Thisisnothingnew,buttakeabitofjsfootounderstandtheeleganceofit.Thiswaydoesnotuseglobalscoped,orweakmaps.Itisaformofreflectionbuiltintothelanguage.Dependingonhowyouleveragethis;onecaneitherforceanexceptionwhichinterruptsthecallstack,orburytheexceptionasanundefined.Thisisdemonstartedbelow,andcanreadmoreaboutthesefeatureshere classClazz{ constructor(){ var_level=1 function_private(x){ return_level*x; } return{ level:_level, public:this.private, public2:function(x){ return_private(x); }, public3:function(x){ return_private(x)*this.public(x); }, }; } private(x){ returnx*x; } } varclazz=newClazz(); console.log(clazz._level);//undefined console.log(clazz._private);//undefined console.log(clazz.level);//1 console.log(clazz.public(1));//1 console.log(clazz.public2(2));//2 console.log(clazz.public3(3));//27 console.log(clazz.private(0));//error Share Follow editedDec7,2019at0:39 answeredOct12,2017at10:32 1-14x0r1-14x0r 1,67711goldbadge1616silverbadges1818bronzebadges Addacomment  |  3 classSomething{ constructor(){ var_property="test"; Object.defineProperty(this,"property",{ get:function(){return_property} }); } } varinstance=newSomething(); console.log(instance.property);//=>"test" instance.property="canreadfromoutside,butcan'twrite"; console.log(instance.property);//=>"test" Share Follow answeredMay1,2016at22:04 IlyaZarembskyIlyaZarembsky 15177bronzebadges 2 2 It'sbesttoavoidcodeonlyanswers.ItwouldbebetterifyoucouldexplainhowyourcodeanswerstheOP'squestion – Stewart_R May1,2016at22:23 Thisisreallyhowtomakeareadonlyvariablemorethanaprivatevariable.Aprivatevariableshouldnotbeaccessibletotheoutside.console.log(instance.property)shouldthroworgiveyouundefined,notgiveyouback"test". – oooyaya Jul13,2017at19:11 Addacomment  |  3 Anotherwaysimilartothelasttwoposted classExample{ constructor(foo){ //privates constself=this; this.foo=foo; //publicinterface returnself.public; } public={ //emptydata nodata:{data:[]}, //noop noop:()=>{}, } //everythingelseprivate bar=10 } consttest=newExample('FOO'); console.log(test.foo);//undefined console.log(test.noop);//{data:[]} console.log(test.bar);//undefined Share Follow answeredNov17,2017at16:15 JayesbeJayesbe 8311silverbadge66bronzebadges Addacomment  |  3 Ifoundaverysimplesolution,justuseObject.freeze().Ofcoursetheproblemisyoucan'taddnothingtotheobjectlater. classCat{ constructor(name,age){ this.name=name this.age=age Object.freeze(this) } } letcat=newCat('Garfield',5) cat.age=6//doesn'twork,eventhrowsanerrorinstrictmode Share Follow answeredMar7,2018at7:48 NikolaAndreevNikolaAndreev 59633silverbadges1717bronzebadges 1 thiswillalsodisablesettermethodlikesetName(name){this.name=name;} – jsdev Oct11,2018at2:33 Addacomment  |  3 Thiscodedemonstratesprivateandpublic,staticandnon-static,instanceandclass-level,variables,methods,andproperties. https://codesandbox.io/s/class-demo-837bj classAnimal{ staticcount=0//classstaticpublic static#ClassPriVar=3//classstaticprivate constructor(kind){ this.kind=kind//instancepublicproperty Animal.count++ letInstancePriVar='InstancePriVar:'+kind//instanceprivateconstructor-var log(InstancePriVar) Animal.#ClassPriVar+=3 this.adhoc='adhoc'//instancepublicpropertyw/outconstructor-parameter } #PawCount=4//instanceprivatevar setPaws(newPawCount){ //instancepublicprop this.#PawCount=newPawCount } getPaws(){ //instancepublicprop returnthis.#PawCount } getGetPriVar(){ //instancepublicprop returnAnimal.#ClassPriVar } staticgetGetPriVarStat(){ //classpublicprop returnAnimal.#ClassPriVar } PrintKind(){ //instancepublicmethod log('kind:'+this.kind) } ReturnKind(){ //instancepublicfunction returnthis.kind } /*Maybeunsupported get#PrivMeth(){//instanceprivateprop returnAnimal.#ClassPriVar+'PrivateMethod' } staticget#PrivMeth(){//classprivateprop returnAnimal.#ClassPriVar+'PrivateMethod' } */ } functionlog(str){ console.log(str) } //TESTING log(Animal.count)//static,availw/outinstance log(Animal.GetPriVarStat)//static,availw/outinstance letA=newAnimal('Cat') log(Animal.count+':'+A.kind) log(A.GetPriVar) A.PrintKind() A.Paws=6 log('Paws:'+A.Paws) log('ReturnKind:'+A.ReturnKind()) log(A.adhoc) letB=newAnimal('Dog') log(Animal.count+':'+B.kind) log(B.GetPriVar) log(A.GetPriVar)//returnssameasB.GetPriVar.Actslikeaclass-levelproperty,butcalledlikeaninstance-levelproperty.It'scuznon-statfxrequiresinstance. log('class:'+Animal.GetPriVarStat) //undefined log('instance:'+B.GetPriVarStat)//staticclassfx log(Animal.GetPriVar)//non-statinstancefx log(A.InstancePriVar)//private log(Animal.InstancePriVar)//privateinstancevar log('PawCount:'+A.PawCount)//private.Usegetter /*log('PawCount:'+A.#PawCount)//private.Usegetter log('PawCount:'+Animal.#PawCount)//Instanceandprivate.Usegetter*/ Share Follow editedApr14,2020at0:36 answeredApr14,2020at0:23 johnywhyjohnywhy 1,77077goldbadges2121silverbadges4848bronzebadges Addacomment  |  3 Readingthepreviousanswerithoughtthatthisexamplecansummarisetheabovesolutions constfriend=Symbol('friend'); constClassName=((hidden,hiddenShared=0)=>{ classClassName{ constructor(hiddenPropertyValue,prop){ this[hidden]=hiddenPropertyValue*++hiddenShared; this.prop=prop } gethidden(){ console.log('gettinghidden'); returnthis[hidden]; } set[friend](v){ console.log('settinghiddenShared'); hiddenShared=v; } getcounter(){ console.log('gettinghiddenShared'); returnhiddenShared; } getprivileged(){ console.log('callingprivilegedmethod'); returnprivileged.bind(this); } } functionprivileged(value){ returnthis[hidden]+value; } returnClassName; })(Symbol('hidden'),0); constOtherClass=(()=>classOtherClassextendsClassName{ constructor(v){ super(v,100); this[friend]=this.counter-1; } })(); UPDATE nowisitpossibletomaketrueprivatepropertiesandmethods(atleastonchromebasedbrowsersfornow). Thesyntaxisprettyneat classMyClass{ #privateProperty=1 #privateMethod(){return2} static#privateStatic=3 static#privateStaticMethod(){return4} staticget#privateStaticGetter(){return5} //alsousingisquitestraightforward method(){ return( this.#privateMethod()+ this.#privateProperty+ MyClass.#privateStatic+ MyClass.#privateStaticMethod()+ MyClass.#privateStaticGetter ) } } newMyClass().method() //returns15 Notethatforretrievingstaticreferencesyouwouldn'tusethis.constructor.#private,becauseitwouldbrakeitssubclasses.Youmustuseareferencetotheproperclassinordertoretrieveitsstaticprivatereferences(thatareavailableonlyinsidethemethodsofthatclass),ieMyClass.#private. Share Follow editedAug21,2020at16:06 answeredJan14,2019at8:19 asdruasdru 1,05799silverbadges1616bronzebadges Addacomment  |  2 Mostanswerseithersayit'simpossible,orrequireyoutouseaWeakMaporSymbol,whichareES6featuresthatwouldprobablyrequirepolyfills.There'showeveranotherway!Checkoutthisout: //1.Createclosure varSomeClass=function(){ //2.Create`key`insideaclosure varkey={}; //Functiontocreateprivatestorage varprivate=function(){ varobj={}; //returnFunctiontoaccessprivatestorageusing`key` returnfunction(testkey){ if(key===testkey)returnobj; //If`key`iswrong,thenstoragecannotbeaccessed console.error('Cannotaccessprivateproperties'); returnundefined; }; }; varSomeClass=function(){ //3.Createprivatestorage this._=private(); //4.Accessprivatestorageusingthe`key` this._(key).priv_prop=200; }; SomeClass.prototype.test=function(){ console.log(this._(key).priv_prop);//Usingpropertyfromprototype }; returnSomeClass; }(); //Canaccessprivatepropertyfromwithinprototype varinstance=newSomeClass(); instance.test();//`200`logged //Cannotaccessprivatepropertyfromoutsideoftheclosure varwrong_key={}; instance._(wrong_key);//undefined;errorlogged Icallthismethodaccessorpattern.Theessentialideaisthatwehaveaclosure,akeyinsidetheclosure,andwecreateaprivateobject(intheconstructor)thatcanonlybeaccessedifyouhavethekey. Ifyouareinterested,youcanreadmoreaboutthisinmyarticle.Usingthismethod,youcancreateperobjectpropertiesthatcannotbeaccessedoutsideoftheclosure.Therefore,youcanusetheminconstructororprototype,butnotanywhereelse.Ihaven'tseenthismethodusedanywhere,butIthinkit'sreallypowerful. Share Follow answeredApr11,2017at17:26 guitarinoguitarino 34811silverbadge77bronzebadges 2 ThequestionwasabouthowtoachievethisinES6classes. – MichaelFranzl Apr18,2017at21:08 YoucanusetheexactsamemethodinES6classes.ES6classesismainlyjustsugarontopoffunctionslikeIpresentedinmyexample.It'squitepossiblethattheoriginalposterisusingatranspiler,inwhichcaseWeakMapsorSymbolswillstillrequirepolyfills.Myanswerisvalidregardless. – guitarino Apr18,2017at21:17 Addacomment  |  2 Seethisanswerforaaclean&simple'class'solutionwithaprivateandpublicinterfaceandsupportforcomposition Share Follow answeredSep23,2017at2:09 kofifuskofifus 13.9k1212goldbadges7878silverbadges133133bronzebadges Addacomment  |  2 Iusethispatternandit'salwaysworkedforme classTest{ constructor(data){ classPublic{ constructor(prv){ //publicfunction(mustbeinconstructoronordertoaccess"prv"variable) connectToDb(ip){ prv._db(ip,prv._err); } } //publicfunctionw/oaccessto"prv"variable log(){ console.log("I'mlogging"); } } //privatevariables this._data=data; this._err=function(ip){ console.log("couldnotconnectto"+ip); } } //privatefunction _db(ip,err){ if(!!ip){ console.log("connectedto"+ip+",sendingdata'"+this.data+"'"); returntrue; } elseerr(ip); } } vartest=newTest(10), ip="185.167.210.49"; test.connectToDb(ip);//true test.log();//I'mlogging test._err(ip);//undefined test._db(ip,function(){console.log("Youhavegothacked!");});//undefined Share Follow answeredMay16,2018at13:31 YamiTeruYamiTeru 2911bronzebadge Addacomment  |  1 2 Next YourAnswer ThanksforcontributingananswertoStackOverflow!Pleasebesuretoanswerthequestion.Providedetailsandshareyourresearch!Butavoid…Askingforhelp,clarification,orrespondingtootheranswers.Makingstatementsbasedonopinion;backthemupwithreferencesorpersonalexperience.Tolearnmore,seeourtipsonwritinggreatanswers. Draftsaved Draftdiscarded Signuporlogin SignupusingGoogle SignupusingFacebook SignupusingEmailandPassword Submit Postasaguest Name Email Required,butnevershown PostYourAnswer Discard Byclicking“PostYourAnswer”,youagreetoourtermsofservice,privacypolicyandcookiepolicy AnswerThisQuestion Nottheansweryou'relookingfor?Browseotherquestionstaggedjavascriptclassecmascript-6private-memberses2022oraskyourownquestion. TheOverflowBlog AIandnanotechnologyareworkingtogethertosolvereal-worldproblems FeaturedonMeta WhatgoesintositesponsorshipsonSE? StackExchangeQ&AaccesswillnotberestrictedinRussia NewUserExperience:DeepDiveintoourResearchontheStagingGround–How... AskWizardforNewUsersFeatureTestisnowLive Linked 155 HowtoimplementprivatemethodinES6classwithTraceur 13 Haveprivateproperties&methodsinES6classes 6 HowtoworkwithprivatevariablesinES6? 6 ES6classesprivatemembersyntax 2 HowtocreateprivatevariablesandmethodsinsideaclassES6? 3 AnalternativewaytoachievedataprivacyinES6Class 1 Cantherebeprivatemembersinanexportedclass? 1 IsthereawaytohaveinternalmethodsonES6classes? 1 Savingapropertyandhavingagetteratthesametime 0 WhatisthesyntaxforprivatemethodinbrowserJavascriptclass(notnode.js)? Seemorelinkedquestions Related 7625 HowdoJavaScriptclosureswork? 2971 HowcanImergepropertiesoftwoJavaScriptobjectsdynamically? 6952 HowdoIremoveapropertyfromaJavaScriptobject? 5656 Whichequalsoperator(==vs===)shouldbeusedinJavaScriptcomparisons? 5919 HowdoIincludeaJavaScriptfileinanotherJavaScriptfile? 8137 Whatdoes"usestrict"doinJavaScript,andwhatisthereasoningbehindit? 685 DoesPythonhave“private”variablesinclasses? 7417 HowtocheckwhetherastringcontainsasubstringinJavaScript? 5302 For-eachoveranarrayinJavaScript 530 ES6classvariablealternatives HotNetworkQuestions Whentoconvertanordinalvariabletoabinaryvariable? Depassivavocecumverbisquaecasumdativumpostulant HowWouldHumanoidsFormTheirOwnGems? Howtomakespacingbetweenanon-fractiontoafractionthesameasfractiontoafractioninmathmode? HowDoesBlackWinThisposition Constructiveproofofstrongnormalizationforsimplytypedlambdacalculus ConnectingHundredsofServersviaLocalNetwork(LAN)? ConvertDateformattoinsertintoMySQLdatabase FrameStringsthatcontainnewlines Spaceshipshooter Isthereamagneticfieldaroundafullychargedcapacitor? Howtogetthelistofconstanttermsoflinearequations? StopPipesFromPullingThroughTheWall CanIsubmitmytaxesinmultipleenvelopes? Separatingbusinesslogicfromdatatemptsmetouseinstanceof Minussignnotaligningwithfraction HowDoesOrbitalWarfareWork? GeometryNodes:Howtomaketubefromcurve Howrealisticisittobecomeaprofessionalmusicianwhenyoustartlearningmusiclateatlife? Howtopolitelystatemoralobjection HasRowlingeverrecognisedmistakesorinconsistencies? GettingonepointwithcoordinatesforpolygoninQGIS HowcanIpreservebooks,butkeepthemaccessible? HowdoyouexplainCanada'sTrudeau'spower-sharingagreementtoafive-year-old(American)? morehotquestions Questionfeed SubscribetoRSS Questionfeed TosubscribetothisRSSfeed,copyandpastethisURLintoyourRSSreader. lang-js Yourprivacy Byclicking“Acceptallcookies”,youagreeStackExchangecanstorecookiesonyourdeviceanddiscloseinformationinaccordancewithourCookiePolicy. Acceptallcookies Customizesettings  



請為這篇文章評分?