Känner du till termen "spagetti kod"? Det här är en metafor som du kan höra från icke-JavaScript-utvecklare i kritik av språket. Det är kod utan struktur. Den kommer att bestå av rad efter rad uttalanden. Vissa kan vara inslagna i funktioner, vissa inte alls. Och om du har tur, kommer alla 9 000 streckkoder att vara i en fil. Denna "spaghetti" -struktur är förmodligen resultatet av procedurprogrammering.
Vid procedurprogrammering används funktioner för att utföra uppgifter. Vi behöver funktioner, men vi behöver också en design som vi kan arbeta med. Och medan spagetti är bra till middag, är det inte för kod. Motgiften är objektorienterad programmering. För att förstå objektorienterad programmering kommer vi att täcka utformning av ett program, definiera klasser och skapa objekt.
Låt oss föreställa dig att du har fått uppgiften att göra en ansökan om en bokhandel. Bara för skojs skull, låt oss ringa vår bokhandel Amazonia. Amazonia kommer att ha böcker. Det kommer att finnas recensioner för böcker. Och vi vill se upp böcker av författare. Det kommer att finnas fler funktioner vi vill implementera i vår app, men det räcker för nu.
Objektorienterad programmering är inriktad på att skapa objekt. Så hur går det att översätta dessa krav till objekt? En teknik är att göra en lista över substantiverna från vår beskrivning och sedan förfina listan till de som är relevanta för problemet. Vi nämnde följande substantiv i vårt problem:
Ansökan är ett irrelevant substantiv, så det kan kasseras. Vi kan också bli av med bokhandel eftersom det liknar ansökan. Om vi behövde göra något med flera bokhandlar kunde vi behålla det. Vi är kvar med böcker, recensioner och författare. (Författare har blivit pluraliserade eftersom vi kommer att ha flera författare i den här applikationen.)
Låt oss nu titta på hur vi ska utforma varje klass. En klass är en ritning för att skapa objekt. Bokskolan vi skapar ger oss en ritning för att skapa bokobjekt.
Det liknar hur en arkitekt använder en ritning för att skapa hus. I ritningen visas sovrum, badrum, kök och vardagsrum. Många hus kan göras från denna plan. Men de behöver inte alla vara samma. Varje hus kan anpassas genom att byta färg, golv eller fixturer.
Skriv de klasser du skulle använda för ett kundvagnsprogram. Kundvagnen ska kunna göra följande:
För att utforma vår bokklass måste vi överväga vad klassen är ansvarig för att veta och vad den är ansvarig för. För en bok behöver vi veta titeln, författaren och ISBN. Dessa är våra data attribut.
Några saker som klassen behöver för att kunna göra är att få och ställa in titeln, få och ställa författaren och få och ställa in ISBN. Dessa kommer att vara klassens metoder. Här är vad vår bokklass ska se ut enligt våra krav:
klassbok konstruktör (titel, författare, isbn) this.title = title; this.author = author; this.isbn = isbn; getTitle () returnera this.title; setTitle (newTitle) this.title = newTitle; getAuthor () returnera detta.author; setAuthor (newAuthor) this.author = newAuthor; getIsbn () returnera this.isbn; setIsbn (newIsbn) this.isbn = newIsbn;
Enligt konventionen klassificeras klassnamnet. Konstruktören är en speciell funktion som deklarerar och initialiserar dataattributen. Inne i konstruktörsfunktionen läggs attributen med användning av detta
nyckelord. Därefter anges några metoder i klassen utan några separatorer.
Metoder som börjar med skaffa sig
är kända som accessor metoder eftersom de returnerar ett värde. Metoder som börjar med uppsättning
är mutatormetoder eftersom de lagrar ett värde eller ändrar värdet på ett attribut.
Det här är den allmänna formen för att definiera en klass:
klass Klassnamn konstruktör (... args) this.attr = arg1; this.attr2 = arg2; ... methodOne () ... methodTwo () ...
En klass kan också deklareras med den här syntaxen:
const ClassName = class ...
Klasser kan också ha statiska metoder. En statisk metod är en metod som är en egenskap hos klassen, inte objektet. Låt oss säga att vi vill skapa en statisk metod för vår bokklass att generera ids. Detta är syntaxen:
klassbok constructor () ... static generateId () ...
Att ringa metoden:
Book.generateId ();
En naturlig fråga skulle vara när och varför skulle du använda en statisk metod? Jag kan inte säga att jag vet en bra anledning att använda statiska metoder. Det beror på hur du utformar din klass. En statisk metod kan användas som hjälpmedel för dina objekt, men då kan sådana funktioner lagras i sin egen klass. Om du vet ett bra användningsfall lämna dina tankar i kommentarerna.
Slutligen, för organisation, bör du lagra en klass som en modul. En modul är bara en fil som innehåller din kod. För att göra vår bokklass till en modul lägger vi till en exportera
uttalande inför det.
export klass bok ...
För att använda bokklassen i en annan fil importerar vi den.
importera bok från boken
Där det innehåller de värden som exporterades från modulen, och
från boken
är en hänvisning till filen Book.js.
Definiera en klass för författare och recensioner.
Klassen i sig är värdelös för oss om vi inte gör något med det. Vi vill skapa böcker. För att kunna göra det måste vi ordna klassen. Instantiate är den tekniska termen för att skapa nya objekt. Vi kallar objektet som skapas från klassen en förekomst. Så här skulle vi skapa en ny instans av en bok:
låt boka = ny bok ("stora förväntningar", "Charles Dickens", 1234); book.getTitle () // Great Expectations
Objekt måste ordnas med ny
operatör. Data som skickas in i objektet är parametrarna som vi definierade i vår konstruktör. Detta är den allmänna formen för instantiating en klass:
variableName = nytt klassnamn (... args);
Antag att vi vill lägga till attribut i vår bokklass som ett ID, pris och nummer på lager. Vi har nu sex parametrar i vår konstruktör, och det är inte söt. Det är inte bara dåligt att titta på. Det skapar extra ansträngning för utvecklare som använder klassen eftersom de måste känna till argumentets ordning. En bättre lösning är att skicka ett objekt som ett argument. Exempel:
klassbok constructor (data) this.id = data.id; this.title = data.title; this.author = data.author; this.isbn = data.isbn; this.units = data.units; this.price = data.price; getTitle () returnera this.title; ...
För att instantiera objektet:
låt data = id: 1, titel: "Stora förväntningar", författare: "Charles Dickens", isbn: 1234, enheter: 10, pris: 29.95 låt boka = ny bok (data);
I vårt exempel kunde vi också få tillgång till titeln med uttalandet boktitel
eftersom alla attribut i klassen är offentliga. Nu kanske du undrar varför jag skapade alla dessa metoder om vi direkt kan komma åt attributen. Var det bara för att visa dig syntaxen? Ja. Jag vill också visa fördelarna med att organisera din kod på detta sätt.
Bundlingrelaterad kod till ett objekt är känd som inkapsling. En av fördelarna med inkapsling är att dölja data. Datafelter innebär att objektets attribut inte kan nås utanför klassen.
På andra språk som Java och Python kan vi ha privata attribut och privata metoder. Eftersom alla våra data är offentliga som standard i en JavaScript-klass kan vi inte utnyttja den här funktionen. Ändå borde vi få tillgång till våra data med getters och setters. En konvention är att prefixa ett attribut med ett understreck _
för att signalera att det är privat.
Skapa ett bokobjekt som använder ett författobjekt för att ange författarattributet.
Vi har lärt oss att en klass är en ritning för att skapa objekt, och ett objekt är en förekomst av en klass. Fördelen med att bygga programvara i objekt är att det ger en programstruktur och gör den mer hanterbar.
När vi har ett stort program kan delarna utvecklas och bibehållas oberoende av andra delar. Med denna modularitet kommer återanvändning. Eftersom vår kod är inkapslad kan objekten om och om igen användas i andra delar av programmet. Dessutom har vi en kodkod som kan testas. Ju bättre testat vår kod är desto säkrare är det från buggar.