Class basic syntax - The Modern JavaScript Tutorial
文章推薦指數: 80 %
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
延伸文章資訊
- 1Class basic syntax - The Modern JavaScript Tutorial
First, a function created by class is labelled by a special internal property [[IsClassConstructo...
- 2Public class fields - JavaScript - MDN Web Docs
Both static and instance public fields are writable, enumerable, and configurable properties. As ...
- 3Private properties in JavaScript ES6 classes - Stack Overflow
Short answer, no, there is no native support for private properties with ES6 classes. But you cou...
- 4JavaScript Class (類別) - Shubo 的程式開發筆記
這篇文章將會解釋JavaScript class 的觀念以及使用方法,包含class ... 這種Arrow Functions in Class Properties 的寫法,非常有用,可以用...
- 5JavaScript Classes - W3Schools
Class methods are created with the same syntax as object methods. Use the keyword class to create...