Tải bản đầy đủ (.pdf) (242 trang)

Type script

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.28 MB, 242 trang )


TableofContents
Introduction

1.1

GettingStarted

1.2

WhyTypeScript

1.2.1

JavaScript

1.3

Awful

1.3.1

FutureJavaScriptNow
Classes

1.4
1.4.1

ClassesEmit

1.4.1.1



ClassesSuper

1.4.1.2

ClassesExtensibility

1.4.1.3

ArrowFunctions

1.4.2

RestParameters

1.4.3

let

1.4.4

const

1.4.5

Destructuring

1.4.6

for...of


1.4.7

Iterators

1.4.8

TemplateStrings

1.4.9

SpreadOperator

1.4.10

Enums

1.4.11

Promise

1.4.12

Generators

1.4.13

AsyncAwait

1.4.14


Project

1.5

CompilationContext
tsconfig.json

1.5.1
1.5.1.1

DeclarationSpaces

1.5.2

Modules

1.5.3

FileModuleDetails

1.5.3.1

globals.d.ts

1.5.3.2

2



Namespaces

1.5.4

NodeJSQuickStart

1.6

BrowserQuickStart

1.7

TypeScript'sTypeSystem

1.8

JSMigrationGuide

1.8.1

AmbientDeclarations

1.8.2

DeclarationFiles

1.8.2.1

Variables


1.8.2.2

Interfaces

1.8.2.3

lib.d.ts

1.8.3

Functions

1.8.4

TypeAssertion

1.8.5

Freshness

1.8.6

TypeGuard

1.8.7

StringLiteralType

1.8.8


Readonly

1.8.9

TypeInference

1.8.10

TypeCompatibility

1.8.11

DiscriminatedUnions

1.8.12

JSX

1.9

TIPs

1.10

QuickObjectReturn

1.10.1

StringBasedEnums


1.10.2

NominalTyping

1.10.3

StatefulFunctions

1.10.4

BindisBad

1.10.5

Currying

1.10.6

TypeInstantiation

1.10.7

LazyObjectLiteralInitialization

1.10.8

ClassesareUseful

1.10.9


AvoidExportDefault

1.10.10

LimitPropertySetters

1.10.11

nullisbad

1.10.12

outFilecaution

1.10.13
3


JQuerytips

1.10.14

staticconstructors

1.10.15

singletonpattern

1.10.16


Functionparameters

1.10.17

Truthy

1.10.18

StyleGuide

1.11

CommonErrors

1.12

TypeScriptCompilerInternals

1.13

Program

1.13.1

AST

1.13.2
TIP:VisitChildren

1.13.2.1


TIP:SyntaxKindenum

1.13.2.2

Trivia

1.13.2.3

Scanner

1.13.3

Parser

1.13.4

ParserFunctions
Binder

1.13.4.1
1.13.5

BinderFunctions

1.13.5.1

BinderDeclarations

1.13.5.2


BinderContainer

1.13.5.3

BinderSymbolTable

1.13.5.4

BinderErrorReporting

1.13.5.5

Checker

1.13.6

CheckerDiagnostics

1.13.6.1

CheckerErrorReporting

1.13.6.2

Emitter

1.13.7

EmitterFunctions


1.13.7.1

EmitterSourceMaps

1.13.7.2

Contributing

1.13.8

4


Introduction

TypeScriptDeepDive
I'vebeenlookingattheissuesthatturnupcommonlywhenpeoplestartusingTypeScript.
ThisisbasedonthelessonsfromStackOverflow/DefinitelyTypedandgeneralengagement
withtheTypeScriptcommunity.Youcanfollowforupdatesanddon'tforgetto★onGithub

GetStarted
Ifyouareheretoreadthebookonlinegetstarted.

OtherOptions
Youcanalsodownloadoneofthefollowing:
EPUBforiPad,iPhone,Mac
PDFforWindowsandothers
MOBIforKindle


SpecialThanks
Alltheamazingcontributors

Share
ShareURL: />
5


GettingStarted

GettingStartedwithTypeScript
TypeScriptVersion

GettingStartedWithTypeScript
TypeScriptcompilesintoJavaScript.JavaScriptiswhatyouareactuallygoingtoexecute
(eitherinthebrowserorontheserver).Soyouaregoingtoneedthefollowing:
TypeScriptcompiler(OSSavailableinsourceandonNPM)
ATypeScripteditor(youcanusenotepadifyouwantbutIusealm )

TypeScriptVersion
InsteadofusingthestableTypeScriptcompilerwewillbepresentingalotofnewstuffinthis
bookthatmaynotbeassociatedwithaversionnumberyet.Igenerallyrecommendpeople
tousethenightlyversionbecausethecompilertestsuiteonlycatchesmorebugsover
time.
Youcaninstallitonthecommandlineas
npminstall-gtypescript@next

6



GettingStarted

Andnowthecommandline tscwillbethelatestandgreatest.VariousIDEssupportittoo,
e.g.
almalwaysshipswiththelatestTypeScriptversion.

Youcanaskvscodetousethisversionbycreating .vscode/settings.jsonwiththe
followingcontents:
{
"typescript.tsdk":"./node_modules/typescript/lib"
}

TypeScriptdefinitions
TypeScripthasaconceptofadeclarationfileforexternalJavaScriptcodebases.High
qualityfilesexistfornearly90%ofthetopJavaScriptlibrariesoutthereinaprojectcalled
DefinitelyTyped.Youwillneed typingstogetthesedefintions.Don'tworry,wewillexplain
whatthismeanslater...justinstallfornow:
npminstall-gtypings

GettingtheSourceCode
Thesourceforthisbookisavailableinthebooksgithubrepository
mostofthecodesamplescan
becopiedintoalmandyoucanplaywiththemasis.Forcodesamplesthatneedadditional
setup(e.g.npmmodules),wewilllinkyoutothecodesamplebeforepresentingthecode.
e.g.
this/will/be/the/link/to/the/code.ts

//Thiswillbethecodeunderdiscussion

WithadevsetupoutofthewayletsjumpintoTypeScriptsyntax.


7


WhyTypeScript

WhyTypeScript
TherearetwomaingoalsofTypeScript:
ProvideanoptionaltypesystemforJavaScript.
ProvideplannedfeaturesfromfutureJavaScripteditionstocurrentJavaScriptengines
Thedesireforthesegoalsismotivatedbelow.

TheTypeScripttypesystem
Youmightbewondering"WhyaddtypestoJavaScript?"
Typeshaveprovenabilitytoenhancecodequalityandunderstandability.Largeteams
(google,microsoft,facebook)havecontinuallyarrivedatthisconclusion.Specifically:
Typesincreaseyouragilitywhendoingrefactoring.Itsbetterforthecompilertocatch
errorsthantohavethingsfailatruntime.
Typesareoneofthebestformsofdocumentationyoucanhave.Thefunctionsignature
isatheoremandthefunctionbodyistheproof.
Howevertypeshaveawayofbeingunnecessarilyceremonious.TypeScriptisvery
particularaboutkeepingthebarriertoentryaslowaspossible.Here'show:

YourJavaScriptisTypeScript
TypeScriptprovidescompiletimetypesafetyforyourJavaScriptcode.Thisisnosurprise
givenitsname.Thegreatthingisthatthetypesarecompletelyoptional.YourJavaScript
code .jsfilecanberenamedtoa .tsfileandTypeScriptwillstillgiveyoubackvalid
.jsequivalenttotheoriginalJavaScriptfile.TypeScriptisintentionallyandstrictlya

supersetofJavaScriptwithoptionalTypechecking.


TypescanbeImplicit
TypeScriptwilltrytoinferasmuchofthetypeinformationasitcaninordertogiveyoutype
safetywithminimalcostofproductivityduringcodedevelopment.Forexample,inthe
followingexampleTypeScriptwillknowthatfooisoftype numberbelowandwillgivean
erroronthesecondlineasshown:

8


WhyTypeScript

varfoo=123;
foo='456';//Error:cannotassign`string`to`number`
//Isfooanumberorastring?

Thistypeinferenceiswellmotivated.Ifyoudostufflikeshowninthisexample,then,inthe
restofyourcode,youcannotbecertainthat fooisa numberora string.Suchissues
turnupofteninlargemulti-filecodebases.Wewilldeepdiveintothetypeinferencerules
later.

TypescanbeExplicit
Aswe'vementionedbefore,TypeScriptwillinferasmuchasitcansafely,howeveryoucan
useannotationsto:
1. Helpalongthecompiler,andmoreimportantlydocumentstuffforthenextdeveloper
whohastoreadyourcode(thatmightbefutureyou!).
2. Enforcethatwhatthecompilersees,iswhatyouthoughtitshouldsee.Thatisyour
understandingofthecodematchesanalgorithmicanalysisofthecode(donebythe
compiler).
TypeScriptusespostfixtypeannotationspopularinotheroptionallyannotatedlanguages

(e.g.ActionScriptandF#).
varfoo:number=123;

Soifyoudosomethingwrongthecompilerwillerrore.g.:
varfoo:number='123';//Error:cannotassigna`string`toa`number`

WewilldiscussallthedetailsofalltheannotationsyntaxsupportedbyTypeScriptinalater
chapter.

Typesarestructural
Insomelanguages(specificallynominallytypedones)statictypingresultsinunnecessary
ceremonybecauseeventhoughyouknowthatthecodewillworkfinethelanguage
semanticsforceyoutocopystuffaround.ThisiswhystufflikeautomapperforC#isvitalfor
C#.InTypeScriptbecausewereallywantittobeeasyforJavaScriptdeveloperswitha

9


WhyTypeScript

minimumcognitiveoverload,typesarestructural.Thismeansthatducktypingisafirstclass
languageconstruct.Considerthefollowingexample.Thefunction iTakePoint2Dwillaccept
anythingthatcontainsallthethings( xand y)itexpects:
interfacePoint2D{
x:number;
y:number;
}
interfacePoint3D{
x:number;
y:number;

z:number;
}
varpoint2D:Point2D={x:0,y:10}
varpoint3D:Point3D={x:0,y:10,z:20}
functioniTakePoint2D(point:Point2D){/*dosomething*/}
iTakePoint2D(point2D);//exactmatchokay
iTakePoint2D(point3D);//extrainformationokay
iTakePoint2D({x:0});//Error:missinginformation`y`

TypeerrorsdonotpreventJavaScriptemit
TomakeiteasyforyoutomigrateyourJavaScriptcodetoTypeScript,evenifthereare
compilationerrors,bydefaultTypeScriptwillemitvalidJavaScriptthebestthatitcan.e.g.
varfoo=123;
foo='456';//Error:cannotassigna`string`toa`number`

willemitthefollowingjs:
varfoo=123;
foo='456';

SoyoucanincrementallyupgradeyourJavaScriptcodetoTypeScript.Thisisverydifferent
fromhowmanyotherlanguagecompilersworkandyetanotherreasontomoveto
TypeScript.

Typescanbeambient
AmajordesigngoalofTypeScriptwastomakeitpossibleforyoutosafelyandeasilyuse
existingJavaScriptlibrariesinTypeScript.TypeScriptdoesthisbymeansofdeclaration.
TypeScriptprovidesyouwithaslidingscaleofhowmuchorhowlittleeffortyouwanttoput

10



WhyTypeScript

inyourdeclarations,themoreeffortyouputthemoretypesafety+codeintelligenceyou
get.NotethatdefinitionsformostofthepopularJavaScriptlibrarieshavealreadybeen
writtenforyoubytheDefinitelyTypedcommunitysoformostpurposeseither:
1. Thedefinitionfilealreadyexists.
2. Orattheveryleast,youhaveavastlistofwellreviewedTypeScriptdeclaration
templatesalreadyavailable
Asaquickexampleofhowyouwouldauthoryourowndeclarationfile,consideratrivial
exampleofjquery.Bydefault(asistobeexpectedofgoodJScode)TypeScriptexpectsyou
todeclare(i.e.use varsomewhere)beforeyouuseavariable
$('.awesome').show();//Error:cannotfindname`$`

AsaquickfixyoucantellTypeScriptthatthereisindeedsomethingcalled $:
declarevar$:any;
$('.awesome').show();//Okay!

Ifyouwantyoucanbuildonthisbasicdefinitionandprovidemoreinformationtohelp
protectyoufromerrors:
declarevar$:{
(selector:string)=>any;
};
$('.awesome').show();//Okay!
$(123).show();//Error:selectorneedstobeastring

WewilldiscussthedetailsofcreatingTypeScriptdefinitionsforexistingJavaScriptindetail
lateronceyouknowmoreaboutTypeScript(e.g.stufflike interfaceandthe any).

FutureJavaScript=>Now

TypeScriptprovidesanumberoffeaturesthatareplannedinES6forcurrentJavaScript
engines(thatonlysupportES5etc).Thetypescriptteamisactivelyaddingthesefeatures
andthislistisonlygoingtogetbiggerovertimeandwewillcoverthisinitsownsection.But
justasaspecimenhereisanexampleofaclass:

11


WhyTypeScript

classPoint{
constructor(publicx:number,publicy:number){
}
add(point:Point){
returnnewPoint(this.x+point.x,this.y+point.y);
}
}
varp1=newPoint(0,10);
varp2=newPoint(10,20);
varp3=p1.add(p2);//{x:10,y:30}

andthelovelyfatarrowfunction:
varinc=(x)=>x+1;

Summary
InthissectionwehaveprovidedyouwiththemotivationanddesigngoalsofTypeScript.
WiththisoutofthewaywecandigintothenittygrittydetailsofTypeScript.

12



JavaScript

YourJavaScriptisTypeScript
Therewere(andwillcontinuetobe)alotofcompetitorsinSomesyntaxtoJavaScript
compilers.TypeScriptisdifferentfromtheminthatYourJavaScriptisTypeScript.Here'sa
diagram:

HoweveritdoesmeanthatyouneedtolearnJavaScript(thegoodnewisyouonlyneedto
learnJavaScript).TypeScriptisjuststandardizingallthewaysyouprovidegood
documentationonJavaScript.
Justgivingyouanewsyntaxdoesn'thelpfixbug(lookingatyouCoffeeScript).
Creatinganewlanguageabstractsyoutoofarfromyourruntimes,communities
(lookingatyouDart).
TypeScriptisjustJavaScriptwithdocs.

13


JavaScript

MakingJavaScriptBetter
TypeScriptwilltrytoprotectyoufromportionsofJavaScriptthatneverworked(soyoudon't
needtorememberthisstuff):
[]+[];//JavaScriptwillgiveyou""(whichmakeslittlesense),TypeScriptwiller
ror
//
//otherthingsthatarenonsensicalinJavaScript
//-don'tgivearuntimeerror(makingdebugginghard)
//-butTypeScriptwillgiveacompiletimeerror(makingdebuggingunnecessary)

//
{}+[];//JS:0,TSError
[]+{};//JS:"[objectObject]",TSError
{}+{};//JS:NaN,TSError
"hello"-1;//JS:NaN,TSError

EssentaillyTypeScriptislintingJavaScript.Justdoingabetterjobatitthenotherlintersthat
don'thavetypeinformation.

YoustillneedtolearnJavaScript
ThatsaidTypeScriptisverypragmaticaboutthefactthatyoudowriteJavaScriptsothere
aresomethingsaboutJavaScriptthatyoustillneedtoknowinordertonotbecaughtoffguard.Letsdiscussthemnext.

14


Awful

JavaScripttheawfulparts
Herearesomeawful(misunderstood)partsofJavaScriptthatyoumustknow.
Note:TypeScriptisasupersetofJavaScript.Justwithdocumentationthatcanactually
beusedbycompilers/IDEs;)

NullandUndefined
Factisyouwillneedtodealwithboth.Justcheckforeitherwith ==check.
///Imageyouaredoing`foo.bar==undefined`wherebarcanbeoneof:
console.log(undefined==undefined);//true
console.log(null==undefined);//true
console.log(0==undefined);//false
console.log(''==undefined);//false

console.log(false==undefined);//false

So ==undefinedor( ==null)willworkonlyfor undefinedor null.Yougenerallydon't
wanttomakeadistinctionbetweenthetwo.

undefined
RememberhowIsaidyoushoulduse ==null.Ofcourseyoudo(causeIjustsaidit^).
Don'tuseitforrootlevelthings.Instrictmodeifyouuse fooand fooisundefinedyou
geta ReferenceErrorexceptionandthewholecallstackunwinds.
Youshouldusestrictmode...andinfacttheTScompilerwillinsertitforyouifyouuse
modules...moreonthoselaterinthebooksoyoudon'thavetobeexplicitaboutit:)
Sotocheckifavariableisdefinedornotatagloballevelyounormallyuse typeof:
if(typeofsomeglobal==='undefined'){
//someglobalisnowsafetouse
console.log(someglobal);
}

this
15


Awful

Anyaccessto thiskeywordwithinafunctionisactuallycontrolledbyhowthefunctionis
actuallycalled.Itiscommonlyreferredtoasthe callingcontext.
Hereisanexample:
functionfoo(){
console.log(this);
}
foo();//logsouttheglobale.g.`window`inbrowsers

letbar={
foo
}
bar.foo();//Logsout`bar`as`foo`wascalledon`bar`

Sobemindfulofyourusageof this.Ifyouwanttodisconnect thisinaclassfromthe
callingcontextuseanarrowfunction,moreonthatlater.

Next
That'sit.ThosearethesimplemisunderstoodportionsofJavaScriptthatstillresultin
variousbugfordevelopersthatarenewtothelanguage.

16


FutureJavaScriptNow

FutureJavaScript:Now
OneofthemainsellingpointsofTypeScriptisthatitallowsyoutouseabunchoffeatures
fromES6andbeyondincurrent(ES3andES5level)JavaScriptengines(likecurrent
browsersandNodeJS).Herewedeepdiveintowhythesefeaturesareusefulfollowedby
howthesefeaturesareimplementedinTypeScript.
Note:NotallofthesefeaturesareslatedforimmediateadditiontoJavaScriptbutprovide
greatutilitytoyourcodeorganizationandmaintenance.Alsonotethatyouarefreetoignore
anyoftheconstructsthatdon'tmakesenseforyourproject,althoughyouwillendupusing
mostofthemeventually;)

17



Classes

Classes
ThereasonwhyitsimportanttohaveclassesinJavaScriptasafirstclassitemisthat:
1. Classesofferausefulstructuralabstraction
2. Providesaconsistentwayfordeveloperstouseclassesinsteadofeveryframework
(emberjs,reactjsetc)comingupwiththeirownversion.
3. ObjectOrientedDevelopersalreadyunderstandclasses.
FinallyJavaScriptdeveloperscanhave class.HerewehaveabasicclasscalledPoint:
classPoint{
x:number;
y:number;
constructor(x:number,y:number){
this.x=x;
this.y=y;
}
add(point:Point){
returnnewPoint(this.x+point.x,this.y+point.y);
}
}
varp1=newPoint(0,10);
varp2=newPoint(10,20);
varp3=p1.add(p2);//{x:10,y:30}

ThisclassgeneratesthefollowingJavaScriptonES5emit:
varPoint=(function(){
functionPoint(x,y){
this.x=x;
this.y=y;
}

Point.prototype.add=function(point){
returnnewPoint(this.x+point.x,this.y+point.y);
};
returnPoint;
})();

ThisisafairlyidiomatictraditionalJavaScriptclasspatternnowasafirstclasslanguage
construct.Notethat constructorisoptional.

Inheritance

18


Classes

ClassesinTypeScript(likeotherlanguages)supportsingleinheritanceusingthe extends
keywordasshownbelow:
classPoint3DextendsPoint{
z:number;
constructor(x:number,y:number,z:number){
super(x,y);
this.z=z;
}
add(point:Point3D){
varpoint2D=super.add(point);
returnnewPoint3D(point2D.x,point2D.y,this.z+point.z);
}
}


Ifyouhaveaconstructorinyourclassthenyoumustcalltheparentconstructorfromyour
constructor(TypeScriptwillpointthisouttoyou).Thisensuresthatthestuffthatitneedsto
seton thisgetsset.Followedbythecallto superyoucanaddanyadditionalstuffyou
wanttodoinyourconstructor(hereweaddanothermember z).
Notethatyouoverrideparentmemberfunctionseasily(hereweoverride add)andstilluse
thefunctionalityofthesuperclassinyourmembers(using super.syntax).

Statics
TypeScriptclassessupport staticpropertiesthataresharedbyallinstancesoftheclass.
Anaturalplacetoput(andaccess)themisontheclassitselfandthatiswhatTypeScript
does:
classSomething{
staticinstances=0;
constructor(){
Something.instances++;
}
}
vars1=newSomething();
vars2=newSomething();
console.log(Something.instances);//2

Youcanhavestaticmembersaswellasstaticfunctions.

AccessModifiers

19


Classes


TypeScriptsupportsaccessmodifiers public, privateand protectedwhichdetermine
theaccessibilityofa classmemberasshownbelow:
accessibleon

public

private

protected

classinstances

yes

no

no

class

yes

yes

yes

classchildren

yes


no

yes

Notethatatruntime(inthegeneratedJS)thesehavenosignificancebutwillgiveyou
compiletimeerrorsifyouusethemincorrectly.Anexampleofeachisshownbelow:
classFooBase{
publicx:number;
privatey:number;
protectedz:number;
}
//EFFECTONINSTANCES
varfoo=newFooBase();
foo.x;//okay
foo.y;//ERROR:private
foo.z;//ERROR:protected
//EFFECTONCHILDCLASSES
classFooChildextendsFooBase{
constructor(){
super();
this.x;//okay
this.y;//ERROR:private
this.z;//okay
}
}

Asalwaysthesemodifiersworkforbothmemberpropertiesandmemberfunctions.

Abstract
abstractcanbethoughtofasanaccessmodifier.Wepresentitseparatelybecause


opposedtothepreviouslymentionedmodifiersitcanbeona classaswellasanymember
oftheclass.Havingan abstractmodifierprimarilymeansthatsuchfunctionalitycannotbe
directlyinvoked.
abstractmembersarecommonlyusedasameansofprovidingacontractfora

functionalitythatachildclassmustprovide. abstractclassescannotbedirectly
instantiated.Insteadtheusermustcreatesome classthatinheritfromthe abstract

20


Classes

class.

Defineusingconstructor
Havingamemberinaclassandinitializingitlikebelow:
classFoo{
x:number;
constructor(x:number){
this.x=x;
}
}

issuchacommonpatternthatTypeScriptprovidesashorthandwhereyoucanprefixthe
memberwithanaccessmodifieranditisautomaticallydeclaredontheclassandcopied
fromtheconstructor.Sothepreviousexamplecanbere-writtenas(notice public
x:number):


classFoo{
constructor(publicx:number){
}
}

Propertyinitializer
ThisisaniftyfeaturesupportedbyTypeScript(fromES7actually).Youcaninitializeany
memberoftheclassoutsidetheclassconstructor,usefultoprovidedefault(notice members
=[])

classFoo{
members=[];//Initializedirectly
add(x){
this.members.push(x);
}
}

21


ClassesEmit

WhatsupwiththeIIFE
Thejsgeneratedfortheclasscouldhavebeen:
functionPoint(x,y){
this.x=x;
this.y=y;
}
Point.prototype.add=function(point){
returnnewPoint(this.x+point.x,this.y+point.y);

};

ThereasonitswrappedinanImmediately-InvokedFunctionExpression(IIFE)i.e.
(function(){
//BODY
returnPoint;
})();

hastodowithinheritance.ItallowsTypeScripttocapturethebaseclassasavariable
_supere.g.

varPoint3D=(function(_super){
__extends(Point3D,_super);
functionPoint3D(x,y,z){
_super.call(this,x,y);
this.z=z;
}
Point3D.prototype.add=function(point){
varpoint2D=_super.prototype.add.call(this,point);
returnnewPoint3D(point2D.x,point2D.y,this.z+point.z);
};
returnPoint3D;
})(Point);

NoticethattheIIFEallowsTypeScripttoeasilycapturethebaseclass Pointina _super
variableandthatisusedconsistentlyintheclassbody.

__extends
YouwillnoticethatassoonasyouinheritaclassTypeScriptalsogeneratesthefollowing
function:


22


ClassesEmit

var__extends=this.__extends||function(d,b){
for(varpinb)if(b.hasOwnProperty(p))d[p]=b[p];
function__(){this.constructor=d;}
__.prototype=b.prototype;
d.prototype=new__();
};

Here dreferstothederivedclassand breferstothebaseclass.Thisfunctiondoestwo
things:
1. copiesthestaticmembersofthebaseclassontothechildclassi.e. for(varpinb)
if(b.hasOwnProperty(p))d[p]=b[p];

2. setsupthechildclassfunction'sprototypetooptionallylookupmembersontheparent's
protoi.e.effectively d.prototype.__proto__=b.prototype

Peoplerarelyhavetroubleunderstanding1,butmanypeoplestrugglewith2.soan
explanationisinorder

d.prototype.__proto__=b.prototype
AfterhavingtutoredmanypeopleaboutthisIfindthefollowingexplanationtobesimplest.
Firstwewillexplainhowthecodefrom __extendsisequivalenttothesimple
d.prototype.__proto__=b.prototype,andthenwhythislineinitselfissignificant.To

understandallthisyouneedtoknowthesethings:

1.

__proto__

2.

prototype

3. effectof newon thisinsidethecalledfunction
4. effectof newon prototypeand __proto__
AllobjectsinJavaScriptcontaina __proto__member.Thismemberisoftennotaccessible
inolderbrowsers(sometimesdocumentationreferstothismagicalpropertyas
[[prototype]]).Ithasoneobjective:Ifapropertyisnotfoundonanobjectduringlookup

(e.g. obj.property)thenitislookedupat obj.__proto__.property.Ifitisstillnotfound
then obj.__proto__.__proto__.propertytilleither:itisfoundorthelatest .__proto__itselfis
null.ThisexplainswhyJavaScriptiscalledtosupportprototypalinheritanceoutofthebox.
Thisisshowninthefollowingexample,whichyoucanruninthechromeconsoleornodejs:

23


ClassesEmit

varfoo={}
//setuponfooaswellasfoo.__proto__
foo.bar=123;
foo.__proto__.bar=456;
console.log(foo.bar);//123
deletefoo.bar;//removefromobject

console.log(foo.bar);//456
deletefoo.__proto__.bar;//removefromfoo.__proto__
console.log(foo.bar);//undefined

Coolsoyouunderstand __proto__.Anotherusefulinformationisthatall functionsin
JavaScripthaveapropertycalled prototypeandthatithasamember constructor
pointingbacktothefunction.Thisisshownbelow:
functionFoo(){}
console.log(Foo.prototype);//{}i.e.itexistsandisnotundefined
console.log(Foo.prototype.constructor===Foo);//Hasamembercalled`constructor`p
ointingbacktothefunction

Nowletslookateffectof newon thisinsidethecalledfunction.Basically thisinside
thecalledfunctionisgoingtopointtothenewlycreatedobjectthatwillbereturnedfromthe
function.It'ssimpletoseeifyoumutateapropertyon thisinsidethefunction:
functionFoo(){
this.bar=123;
}
//callwiththenewoperator
varnewFoo=newFoo();
console.log(newFoo.bar);//123

Nowtheonlyotherthingyouneedtoknowisthatcalling newonafunctioncopiesthe
prototypeofthefunctionintothe __proto__ofthenewlycreatedobjectthatisreturned

fromthefunctioncall.Hereiscodeyoucanruntocompletelyunderstandit:
functionFoo(){}
varfoo=newFoo();
console.log(foo.__proto__===Foo.prototype);//True!


That'sit.Nowlookatthefollowingstraightoutof __extends.I'vetakethelibertytonumber
theselines:

24


ClassesEmit

1function__(){this.constructor=d;}
2__.prototype=b.prototype;
3d.prototype=new__();

Readingthisfunctioninreversethe d.prototype=new__()online3effectivelymeans
d.prototype={__proto__:__.prototype}(becauseoftheeffectof newon prototypeand
__proto__),combineitwiththepreviousline(i.e.line2 __.prototype=b.prototype;)you

get d.prototype={__proto__:b.prototype}.
Butwaitwewanted d.prototype.__proto__i.e.justtheprotochangedandmaintaintheold
d.prototype.constructor.Thisiswherethesignificanceofthefirstline(i.e. function__(){
this.constructor=d;})comesin.Herewewilleffectivelyhave d.prototype={__proto__:
__.prototype,d.constructor=d}(becauseoftheeffectof newon thisinsidethecalled

function).Sosincewerestore d.prototype.constructor,theonlythingwehavetruly
mutatedisthe __proto__hence d.prototype.__proto__=b.prototype.

d.prototype.__proto__=b.prototypesignificance
Thesignificanceisthatitallowsyoutoaddmemberfunctionstoachildclassandinherit
othersfromthebaseclass.Thisisdemonstratedbythefollowingsimpleexample:
functionAnimal(){}
Animal.prototype.walk=function(){console.log('walk')};

functionBird(){}
Bird.prototype.__proto__=Animal.prototype;
Bird.prototype.fly=function(){console.log('fly')};
varbird=newBird();
bird.walk();
bird.fly();

Basically bird.flywillbelookedupfrom bird.__proto__.fly(rememberthat newmakes
the bird.__proto__pointto Bird.prototype)and bird.walk(aninheritedmember)willbe
lookedupfrom bird.__proto__.__proto__.walk(as bird.__proto__==Bird.prototypeand
bird.__proto__.__proto__== Animal.prototype).

25


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×