Class basic syntax - The Modern JavaScript Tutorial

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

First, a function created by class is labelled by a special internal property [[IsClassConstructor]]: true . So it's not entirely the same as ... ENARعربيENEnglishESEspañolFRFrançaisIDIndonesiaITItalianoJA日本語KO한국어RUРусскийTRTürkçeUKУкраїнськаZH简体中文Wewanttomakethisopen-sourceprojectavailableforpeopleallaroundtheworld.Helptotranslatethecontentofthistutorialtoyourlanguage! BuyEPUB/PDFSearchSearchTutorialmapLightthemeDarkthemeShareعربيEnglishEspañolFrançaisIndonesiaItaliano日本語한국어РусскийTürkçeУкраїнська简体中文Inobject-orientedprogramming,aclassisanextensibleprogram-code-templateforcreatingobjects,providinginitialvaluesforstate(membervariables)andimplementationsofbehavior(memberfunctionsormethods). Inpractice,weoftenneedtocreatemanyobjectsofthesamekind,likeusers,orgoodsorwhatever. AswealreadyknowfromthechapterConstructor,operator"new",newfunctioncanhelpwiththat. ButinthemodernJavaScript,there’samoreadvanced“class”construct,thatintroducesgreatnewfeatureswhichareusefulforobject-orientedprogramming. The“class”syntaxThebasicsyntaxis: classMyClass{ //classmethods constructor(){...} method1(){...} method2(){...} method3(){...} ... } ThenusenewMyClass()tocreateanewobjectwithallthelistedmethods. Theconstructor()methodiscalledautomaticallybynew,sowecaninitializetheobjectthere. Forexample: classUser{ constructor(name){ this.name=name; } sayHi(){ alert(this.name); } } //Usage: letuser=newUser("John"); user.sayHi(); WhennewUser("John")iscalled: Anewobjectiscreated. Theconstructorrunswiththegivenargumentandassignsittothis.name. …Thenwecancallobjectmethods,suchasuser.sayHi(). Nocommabetweenclassmethods Acommonpitfallfornovicedevelopersistoputacommabetweenclassmethods,whichwouldresultinasyntaxerror. Thenotationhereisnottobeconfusedwithobjectliterals.Withintheclass,nocommasarerequired. Whatisaclass?So,whatexactlyisaclass?That’snotanentirelynewlanguage-levelentity,asonemightthink. Let’sunveilanymagicandseewhataclassreallyis.That’llhelpinunderstandingmanycomplexaspects. InJavaScript,aclassisakindoffunction. Here,takealook: classUser{ constructor(name){this.name=name;} sayHi(){alert(this.name);} } //proof:Userisafunction alert(typeofUser);//function WhatclassUser{...}constructreallydoesis: CreatesafunctionnamedUser,thatbecomestheresultoftheclassdeclaration.Thefunctioncodeistakenfromtheconstructormethod(assumedemptyifwedon’twritesuchmethod). Storesclassmethods,suchassayHi,inUser.prototype. AfternewUserobjectiscreated,whenwecallitsmethod,it’stakenfromtheprototype,justasdescribedinthechapterF.prototype.Sotheobjecthasaccesstoclassmethods. WecanillustratetheresultofclassUserdeclarationas: Here’sthecodetointrospectit: classUser{ constructor(name){this.name=name;} sayHi(){alert(this.name);} } //classisafunction alert(typeofUser);//function //...or,moreprecisely,theconstructormethod alert(User===User.prototype.constructor);//true //ThemethodsareinUser.prototype,e.g: alert(User.prototype.sayHi);//thecodeofthesayHimethod //thereareexactlytwomethodsintheprototype alert(Object.getOwnPropertyNames(User.prototype));//constructor,sayHi NotjustasyntacticsugarSometimespeoplesaythatclassisa“syntacticsugar”(syntaxthatisdesignedtomakethingseasiertoread,butdoesn’tintroduceanythingnew),becausewecouldactuallydeclarethesamethingwithoutusingtheclasskeywordatall: //rewritingclassUserinpurefunctions //1.Createconstructorfunction functionUser(name){ this.name=name; } //afunctionprototypehas"constructor"propertybydefault, //sowedon'tneedtocreateit //2.Addthemethodtoprototype User.prototype.sayHi=function(){ alert(this.name); }; //Usage: letuser=newUser("John"); user.sayHi(); Theresultofthisdefinitionisaboutthesame.So,thereareindeedreasonswhyclasscanbeconsideredasyntacticsugartodefineaconstructortogetherwithitsprototypemethods. Still,thereareimportantdifferences. First,afunctioncreatedbyclassislabelledbyaspecialinternalproperty[[IsClassConstructor]]:true.Soit’snotentirelythesameascreatingitmanually. Thelanguagechecksforthatpropertyinavarietyofplaces.Forexample,unlikearegularfunction,itmustbecalledwithnew: classUser{ constructor(){} } alert(typeofUser);//function User();//Error:ClassconstructorUsercannotbeinvokedwithout'new' Also,astringrepresentationofaclassconstructorinmostJavaScriptenginesstartswiththe“class…” classUser{ constructor(){} } alert(User);//classUser{...} Thereareotherdifferences,we’llseethemsoon. Classmethodsarenon-enumerable. Aclassdefinitionsetsenumerableflagtofalseforallmethodsinthe"prototype". That’sgood,becauseifwefor..inoveranobject,weusuallydon’twantitsclassmethods. Classesalwaysusestrict. Allcodeinsidetheclassconstructisautomaticallyinstrictmode. Besides,classsyntaxbringsmanyotherfeaturesthatwe’llexplorelater. ClassExpressionJustlikefunctions,classescanbedefinedinsideanotherexpression,passedaround,returned,assigned,etc. Here’sanexampleofaclassexpression: letUser=class{ sayHi(){ alert("Hello"); } }; SimilartoNamedFunctionExpressions,classexpressionsmayhaveaname. Ifaclassexpressionhasaname,it’svisibleinsidetheclassonly: //"NamedClassExpression" //(nosuchterminthespec,butthat'ssimilartoNamedFunctionExpression) letUser=classMyClass{ sayHi(){ alert(MyClass);//MyClassnameisvisibleonlyinsidetheclass } }; newUser().sayHi();//works,showsMyClassdefinition alert(MyClass);//error,MyClassnameisn'tvisibleoutsideoftheclass Wecanevenmakeclassesdynamically“on-demand”,likethis: functionmakeClass(phrase){ //declareaclassandreturnit returnclass{ sayHi(){ alert(phrase); } }; } //Createanewclass letUser=makeClass("Hello"); newUser().sayHi();//Hello Getters/settersJustlikeliteralobjects,classesmayincludegetters/setters,computedpropertiesetc. Here’sanexampleforuser.nameimplementedusingget/set: classUser{ constructor(name){ //invokesthesetter this.name=name; } getname(){ returnthis._name; } setname(value){ if(value.length<4){ alert("Nameistooshort."); return; } this._name=value; } } letuser=newUser("John"); alert(user.name);//John user=newUser("");//Nameistooshort. Technically,suchclassdeclarationworksbycreatinggettersandsettersinUser.prototype. Computednames[…]Here’sanexamplewithacomputedmethodnameusingbrackets[...]: classUser{ ['say'+'Hi'](){ alert("Hello"); } } newUser().sayHi(); Suchfeaturesareeasytoremember,astheyresemblethatofliteralobjects. Classfields Oldbrowsersmayneedapolyfill Classfieldsarearecentadditiontothelanguage. Previously,ourclassesonlyhadmethods. “Classfields”isasyntaxthatallowstoaddanyproperties. Forinstance,let’saddnamepropertytoclassUser: classUser{ name="John"; sayHi(){ alert(`Hello,${this.name}!`); } } newUser().sayHi();//Hello,John! So,wejustwrite"="inthedeclaration,andthat’sit. Theimportantdifferenceofclassfieldsisthattheyaresetonindividualobjects,notUser.prototype: classUser{ name="John"; } letuser=newUser(); alert(user.name);//John alert(User.prototype.name);//undefined Wecanalsoassignvaluesusingmorecomplexexpressionsandfunctioncalls: classUser{ name=prompt("Name,please?","John"); } letuser=newUser(); alert(user.name);//John MakingboundmethodswithclassfieldsAsdemonstratedinthechapterFunctionbindingfunctionsinJavaScripthaveadynamicthis.Itdependsonthecontextofthecall. Soifanobjectmethodispassedaroundandcalledinanothercontext,thiswon’tbeareferencetoitsobjectanymore. Forinstance,thiscodewillshowundefined: classButton{ constructor(value){ this.value=value; } click(){ alert(this.value); } } letbutton=newButton("hello"); setTimeout(button.click,1000);//undefined Theproblemiscalled"losingthis". Therearetwoapproachestofixingit,asdiscussedinthechapterFunctionbinding: Passawrapper-function,suchassetTimeout(()=>button.click(),1000). Bindthemethodtoobject,e.g.intheconstructor. Classfieldsprovideanother,quiteelegantsyntax: classButton{ constructor(value){ this.value=value; } click=()=>{ alert(this.value); } } letbutton=newButton("hello"); setTimeout(button.click,1000);//hello Theclassfieldclick=()=>{...}iscreatedonaper-objectbasis,there’saseparatefunctionforeachButtonobject,withthisinsideitreferencingthatobject.Wecanpassbutton.clickaroundanywhere,andthevalueofthiswillalwaysbecorrect. That’sespeciallyusefulinbrowserenvironment,foreventlisteners. SummaryThebasicclasssyntaxlookslikethis: classMyClass{ prop=value;//property constructor(...){//constructor //... } method(...){}//method getsomething(...){}//gettermethod setsomething(...){}//settermethod [Symbol.iterator](){}//methodwithcomputedname(symbolhere) //... } MyClassistechnicallyafunction(theonethatweprovideasconstructor),whilemethods,gettersandsettersarewrittentoMyClass.prototype. Inthenextchapterswe’lllearnmoreaboutclasses,includinginheritanceandotherfeatures. TasksRewritetoclassimportance:5TheClockclass(seethesandbox)iswritteninfunctionalstyle.Rewriteitinthe“class”syntax. P.S.Theclockticksintheconsole,openittosee. Openasandboxforthetask.solution classClock{ constructor({template}){ this.template=template; } render(){ letdate=newDate(); lethours=date.getHours(); if(hours<10)hours='0'+hours; letmins=date.getMinutes(); if(mins<10)mins='0'+mins; letsecs=date.getSeconds(); if(secs<10)secs='0'+secs; letoutput=this.template .replace('h',hours) .replace('m',mins) .replace('s',secs); console.log(output); } stop(){ clearInterval(this.timer); } start(){ this.render(); this.timer=setInterval(()=>this.render(),1000); } } letclock=newClock({template:'h:m:s'}); clock.start(); Openthesolutioninasandbox.PreviouslessonNextlessonShareTutorialmapCommentsreadthisbeforecommenting…Ifyouhavesuggestionswhattoimprove-pleasesubmitaGitHubissueorapullrequestinsteadofcommenting.Ifyoucan'tunderstandsomethinginthearticle–pleaseelaborate.Toinsertfewwordsofcode,usethetag,forseverallines–wrapthemin

tag,formorethan10lines–useasandbox(plnkr,jsbin,codepen…)ChapterClassesLessonnavigationThe“class”syntaxWhatisaclass?NotjustasyntacticsugarClassExpressionGetters/settersComputednames[…]ClassfieldsSummaryTasks(1)CommentsShareEditonGitHub© 2007—2022 IlyaKantorabouttheprojectcontactustermsofusageprivacypolicy



請為這篇文章評分?