OOP un bibliotēku pamati
Tālāk seko apkopojums par pamata lietām, kas ir jāzina par objektorientēto programmēšanu (OOP) un atvērtajām bibliotēkām Programmēšana II kursa ietvaros.
Saturs
JavaScript Datu tipi
Lai izprastu OOP terminus un konceptu, vispirms ir jāiepazīst pamata datu tipi. Tālāk ir apkopota informācija par JavaScript pamata datu tipiem.
Datu tipi JavaScript valodā sastāv no primitīviem un objektiem. Objektos var glabāt datu kolekcijas, primitīvajos datu tipos tikai atsevišķus datus.

Primitīvi
Visi datu veidi, izņemot objektus, definē nemainīgas vērtības (tas ir, vērtības, kuras nevar mainīt). Piemēram, String
ir nemainīgas. Šo veidu vērtības dēvē par "primitīviem".
Boolean
Boolean
ir loģisks datu tips, kuram var būt tikai patiesas (true
) vai nepatiesas (false
) vērtības.
Piemēram, JavaScript valodā Boolean
nosacījumi bieži tiek izmantoti, lai izlemtu, kuras koda sadaļas izpildīt (piemēram, if
sazarojumā) vai atkārtot (piemēram, for
cilpās).
let bool = true;if (bool === true) { console.log("Vērtība ir patiesa"); //sagaidāms, ka izdrukās šo} else { console.log("Vērtība ir nepatiesa");}
Null
Null
tipam ir tieši viena vērtība: null
. Vērtība null norāda apzinātu objekta vērtības neesamību.
Undefined
undefined
ir primitīva vērtība, kas automātiski tiek piešķirta mainīgajiem, kas tikko ir deklarēti, vai formāliem argumentiem, kuriem nav faktisku argumentu.
let und; //definēts mainīgais, bet nav piešķirta vērtībaconsole.log(`und vērtība ir: ${und}`); // => "und vertība ir: undefined"
Number
Number
ir datu tips skaitļiem, kurus var rakstīt ar vai bez decimālzīmēm.
let a = 12;let b = 12.0;
Lielākiem skaitļiem var izmantot datu tipu BigInt
, bet tas ir ārpus ši kursa vajadzībām.
Darbības ar decimālskaitļiem ne vienmēr būs precīzas.
let x = 0.2 + 0.1;console.log(x); // => 0.30000000000000004
Lai risinātu šo neprecizitāti, var izmantot reizināšanu un dalīšanu.
let x = (0.2 * 10 + 0.1 * 10) / 10;console.log(x); // => 0.3
Jāuzmanās saskaitot Number
un String
datu tipus.
let a = 10; //Numberlet b = 50; //Numberlet c = "100"; //Stringconsole.log(a + b); // => 60console.log(typeof a + b); // => numberconsole.log(a + c); // => 10100console.log(typeof a + c); // => string
NaN (Not A Number jeb "Nav skaitlis") parasti rodas, ja aritmētiskās darbības rezultātu nevar izteikt kā skaitli.
String
String
ir rakstzīmju sērija, piemēram, "Vārds uzvārds". String
tiek rakstītas ar pēdiņām - var izmantot vienpēdiņas vai dubultpēdiņas.
Katrs elements String
ieņem noteiktu pozīciju virknē. Pirmais elements atrodas indeksā 0, nākamais indeksā 1 un tā tālāk. Virknes garums ir tajā esošo elementu skaits, ko var noteikt ar metodi .length
.
JavaScript virknes ir nemainīgas. Tas nozīmē, ka pēc virknes izveides to nav iespējams modificēt. Tomēr ir iespējams izveidot citu virkni, izmantojot sākotnējo virkni.
Kā pārvēstu uz citu datu tipu
Citreiz vērtīgi ir pārvērst doto datu tipu uz kādu citu. Lai to izdarītu, var izmantot sekojošas metodes:
toString()
metode pārvērš uzString
datu tipu;Number()
atgriež skaitli (Number
), kas pārveidots no tā argumenta;parseFloat()
pārveido tā argumentu un atgriež kā decimālskaitli;parseInt()
pārveido tā argumentu un atgriež veselu skaitli.
Kā noteikt datu tipu ar typeof
Bieži noder izmantot operatoru typeof
, lai noteiktu datu tipu.
typeof "Vārds"; // "string"typeof 0.21; // "number"typeof true; // "boolean"typeof [1, 2, 3, 4]; // "object"typeof { car: "Volvo", year: 2022 }; // "object"typeof new Date(); // "object"typeof function () {}; // "function"typeof car; // "undefined"
Atšķirība starp ==
un ===
Javascript operatori ==
un !=
tiek izmantoti divu vērtību salīdzināšanai. ==
operators pārbauda, vai divas vērtības ir vienādas. Operators !=
pārbauda, vai divas vērtības nav vienādas. To sauc arī par "vaļīgo" vienlīdzības operatoru, jo tas pārbauda abstrakto vienlīdzību, t.i., tas mēdz pārveidot operandu datu tipus, lai veiktu salīdzināšanu, ja divi operandi nav viena datu tipa.
Operators ===
tiek saukts par stingru vienlīdzības operatoru (un !==
tiek saukts stingri nevienlīdzības operators). Tas neveic operandu tipu konvertēšanu pirms to vērtību salīdzināšanas un atgriež vērtību false, pat ja operandu datu tips nav vienāds.
let a = 1;let b = "1";a == b; //truea === b; //false
Objekti
JavasScript viss, kas nav kāds no pirmitīvu datu tipa, ir objekts.
Date
Date
objekti attēlo vienu laika momentu neatkarīgā formātā. Datuma objektos ir skaitlis, kas apzīmē milisekundes kopš 1970. gada 1. janvāra pēc UTC laika zonas.
Bieži izmanto new Date()
, kas atgriež lietotāja pašreizējo laiku. Tālāk var izmantot metodes:
.getDate()
, kas atgriež mēneša dienu (1-31);.getMonth()
, kas atgriež mēnesi (0-11);.getFullYear()
, kas atgriež gadu (YYYY);- un citas metodes
Array
Array
jeb masīva objekts, tāpat kā masīvi citās programmēšanas valodās, ļauj glabāt dažādu datu kolekciju ar vienu mainīgā nosaukumu. Masīviem ir nulles indekss: pirmais masīva elements ir indeksā 0, otrais ir indeksā 1 un tā tālāk — un pēdējais elements ir masīva garuma vērtībā, no kuras atņemts 1.
Biežāk izmantotās masīvu funkcijas ar paskaidrojumu:
let data = ['Tīģeris', 23, true, 🐯]//noteikt masīva garumudata.length // => 4//piekļūt elementam ar indexudata[0] //=> "Tīģeris"//pievienot elementu masīva galādata.push('draudzīgs') //=> ['Tīģeris', 23, true, 🐯, draudzīgs]//noskaidrot, vai elements ir masīvā un kur atrodasdata.indexOf(true) // => 2data.indexOf(false) // => -1, jo elements nav masīvā//cilpa, lai pārskatītu katru elementudata.forEach(element =>{ console.log(element) //konsolē izdrukās katru elementu})
Object
Lai saprastu, kas ir JavaScript objekts, var iztēloties objektus no dzīves - piemēram, viedierīces. Telefoniem ir savas īpašības - svars, krāsa, ekrāna garums u.c. un katram telefonam šai īpašībai ir vērtība. Tā arī javascript Object
ir īpašību kolekcijas ar vērtībām. Vēl telefoniem ir dažādas metodes (funkcijas). Piemēram, zvanīt, nosūtīt īsziņu, atvērt lietotni.
- Visiem telefoniem ir vienādas īpašības, taču īpašumu vērtības atšķiras atkarībā no telefona.
- Visiem telefoniem ir vienādas metodes, taču metodes tiek veiktas dažādos laikos.
Objektiem atšķirībā no masīviem nav noteiktas kārtības t.i. īpašības nevar izsaukt ar indeksu.
let phoneOne = { svars: 345, krasa: "melna", "ekrāna garums": "5.2" };let phoneTwo = { svars: 270, krasa: "balts", "ekrāna garums": "6" };//izsaukt īpašībuconsole.log(phoneOne.svars); //=> 345console.log(phoneTwo["ekrāna garums"]); //=> 6//piešķirt īpašībai junu vērtībuphoneOne.svars = 200;//pievienot jaunu īpašību un vērtībuphoneOne.camera = true;
Objektorientētā programmēšana (OOP)
Šajā sadaļā apskatīsim jautājumus:
- Kādi ir objektorientētas programmēšanas valodas pamatprincipi?
- Kas ir klase un objekts?
- Kādam nolūkam lieto konstruktorus?
- Kur tiek deklarēti iekšējie mainīgie un funkcijas?
- Kādam nolūkam nepieciešama iekapsulēšana, mantošana, abstrakcija, polimorfisms?
OOP pamatprincipi
Objektorientētā programmēšana (OOP) ir programmēšanas paradigma, kas ir būtiska daudzām programmēšanas valodām, tostarp Java, C++, Python, JavaScript u.c. Objektorientētā programmēšana ir sistēmas modelēšana kā objektu kolekcija, kur katrs objekts attēlo kādu konkrētu sistēmas aspektu. Objekti satur gan funkcijas (vai metodes), gan datus (īpašības).
Lai paskaidrotu saprotamāk OOP principus, varam iztēloties, ka tiek aprakstīts skolas modelis. Skolā ir skolotāji, kurus varētu aprakstīt kā objektus, kuriem ir dažas kopīgas īpašības: viņiem visiem ir vārds un priekšmets, ko viņi māca. Turklāt katrs skolotājs var veikt noteiktas lietas: viņi visi var izlikt vērtējumu un iepazīstināt ar sevi, nosaucot savu vārdu.
Tātad Skolotajs
varētu būt mūsu sistēmas klase. Klases definīcijā ir uzskaitīti dati (īpašības) un metodes, kas ir katram skolotājam. JavaScript to varētu attēlot šādi:
class Skolotajs { vards; prieksmets; constructor(vards, prieksmets) { this.vards = vards; this.prieksmets = prieksmets; } iepazistinatArSevi() { console.log(`Sveiki, mani sauc ${this.vards}!`); } izliktVertejumu(punkti) { if (punkti > 5) { console.log("Priekšmets ir nokārtots!"); } else { console.log("Priekšmets nav nokārtots!"); } }}
Klase (class
) ir sava veida veidne, lai izveidotu konkrētus šāda veida objektus. Katrs konkrētais skolotājs, ko mēs izveidojam, tiek saukts par Skolotajs
klases objektu.
let rinalds = new Skolotajs("Rinalds", "Ģeogrāfija");let sandra = new Skolotajs("Sandra", "Matemātika");rinalds.iepazistinatArSevi(); // Sveiki, mani sauc Rinalds!rinalds.prieksmets; // Ģeogrāfijasandra.iepazistinatArSevi(); // Sveiki, mani sauc Sandra!sandra.prieksmets; // Matemātika
Šādi tiek izveidoti divi klases Skolotajs
objekti ar savām īpašībām un kopīgām metodēm.
Lai izveidotu jaunu objektu ir jāizmanto speciāla funkcija, ko sauc par konstruktoru (constructor
), padodot konkrētas vērtības. Var ievērot, ka constructor
, izmanto īpašu atslēgvārdu this
, kas norāda saiti uz pašreizējo klasi. Šajā gadījumā this
piesaista padotās vērtības definētajām klases īpašībām. No augstāk izmantotā piemēr new Skolotajs("Rinalds", "Ģeogrāfija") , atslēgas vārds this
piesaistī klases īpašībai vards
padoto vērtību "Rinalds" un klases īpašībai prieksmets
padoto vērtību "Ģeogrāfija".
Mantošana
Modelejot tālāk skolas sistēmu, varētu izveidot arī skolēnu klasi (Skolens
). Atšķirībā no skolotājiem, skolēni nevar novērtēt darbus un nemāca konkrētu priekšmetu, bet tie pieder noteiktai klašu grupai.
Tomēr skolēniem ir vārds un viņi var arī iepazīstināt ar sevi. Tāpēc būtu noderīgi, ja varētu attēlot, ka skolotājiem un skolēniem ir kopīgas īpašības un metodes. Mantošana ļauj izdarīt tieši to.
Var novērot, ka gan skolotāji, gan skolēni ir personas, un personām ir vārdi un viņi vēlas sevi iepazīstināt. To var modelēt, definējot jaunu klasi Persona
, kurā var definēt visas personām kopīgās īpašības. Pēc tam šīs kopīgās īpašības un metodes gan Skolotajs
, gan Skolens
var iegūt no Personas
, pievienojot savas individuālās īpašības un metodes.
//Definējam klasi Personaclass Persona { vards; constructor(vards) { this.vards = vards; } iepazistinatArSevi() { console.log(`Sveiki, mani sauc ${this.vards}!`); }}//Definējam klasi Skolotajs, kas manto īpašības un metodes no klases Personaclass Skolotajs extends Persona { prieksmets; constructor(vards, prieksmets) { super(vards); this.prieksmets = prieksmets; } izliktVertejumu(punkti) { if (punkti > 5) { console.log("Priekšmets ir nokārtots!"); } else { console.log("Priekšmets nav nokārtots!"); } }}
Apskatot tuvāk Skolotajs
konstruktoru (constructor), var ievērot, ka vispirms tiek izsaukts virsējās klases konstruktors, izmantojot super()
, nododot vārda parametru. Pēc tam skolotāja konstruktors iestata macību priekšmeta nosaukumu.
Tagad definējot jaunu objektu ar klasi Skolotajs
, tas saņems visas Personas īpašības un metodes un arī Skolotājam raksturīgās īpašības un metodes.
Iekapsulēšana
Lai noteiktu privātas īpašības, kuras nevar izsaukt no citām koda daļām, var lietot iekapsulēšanu. To izmanto, lai vienā objektā apvienotu datu struktūras un atsevišķas funkcijas, novēršot nevēlamus blakusefektus sistēmas darbībā. Piemēram, Skolens
gadījumā varētu gribēt, lai klašu grupa ir privāta t.i. nevar, piemēram, izvadīt tieši kurā klašu grupā skolēns mācās, bet to drīkst izmantot kādā metodē, piemēram, lai noteiktu, vai skolēns mācās pamatskolā vai vidusskolā.
class Skolens extends Persona { #klase; constructor(vards, klase) { super(vards); this.#klase = klase; } macasVidusskola() { return this.#klase > 9; }}
Ar #
tiek atzīmētas īpašības, kas tiek iekapsulētas t.i. nevar izsaukt no citas koda vietas, bet var izmantot metodē klases ietvaros.
let raimonds = new Skolens("Raimonds", 11);raimonds.iepazistinatArSevi(); //=> Sveiki, mani sauc Raimonds!raimonds.#klase; // SyntaxError, jo klase ir iekapsulētaraimonds.macasVidusskola(); // true
Līdzīgi var iekapsulēt arī metodes, tām priekšā pievienojot #
.
Abstrakcija
Abstrakcija ir veids, kā paslēpt sarežģītību jeb pētāmā objekta galveno aspektu izdalīšana un mazsvarīgu aspektu ignorēšana. JavaScript abstrakcijas līdzeklis tiek izmantots, lai paslēptu iekšējās detaļas un parādītu tikai objekta būtiskās iezīmes. Abstrakcija samazina koda dublēšanos un palielina koda atkārtotu izmantošanu.
No augstāk aprakstītajiem piemēriem funkciju izliktVertejumu(punkti)
varētu uzskatīt par abstrakcijas piemēru, jo tā sevī ietver sarežģītāku (lai arī šajā gadījumā nepārāk sarežgītu) loģiku, kas vēlāk ļauj izmantot šo metodi atkārtoti, nevis kontroldaram aprēķināt vērtējumu atkārtoti.
Polimorfisms
Polimorfisms ir OOP princips, kas nodrošina iespēju veikt vienu uzdevumu dažādos veidos.
Piemēram, varētu klasei Skolotajs
pārdefinēt metodi iepazistinatArSevi()
:
class Skolotajs extends Persona { prieksmets; constructor(vards, prieksmets) { super(vards); this.prieksmets = prieksmets; } iepazistinatArSevi() { console.log( `Sveiki, mani sauc ${this.vards}! ${this.prieksmets} ir mans priekšmets.` ); }}let persona = new Persona("Elvis");persona.iepazistinatArSevi(); //=> Sveiki, mani sauc Elvis!let rinalds = new Skolotajs("Rinalds", "Ģeogrāfija");rinalds.iepazistinatArSevi(); //=> Sveiki, mani sauc Rinalds! Ģeogrāfiju ir mans priekšmets.
Šajā piemērā ar vienu un to pašu metodi iepazistinatArSevi()
, tiek veiktas dažādas darbības - konsolē tiek izdrukāti dažādi uzraksti.
JavaScript bibliotēkas
JavaScript bibliotēkas ir iepriekš uzrakstīts JavaScript kods, kas ļauj vieglāk izstrādāt uz JavaScript balstītas lietojumprogrammas. JavaScript bibliotēkas satur dažādas funkcijas, metodes vai objektus, lai veiktu praktiskus uzdevumus tīmekļa lapā vai JS lietojumprogrammā. Arī Boostrap 5 satur JavaScript bibliotēku.
Lai lietotnē izmantotu JavaScript bibliotēku, jāpievieno <script>
elementam src
atribūts, kas norāda bibliotēkas datnes atrašānās vietu vai URL.
Gandrīz visas JavaScript bibliotēkas tiek izlaistas saskaņā ar atļauju vai copyleft licenci, lai nodrošinātu izplatīšanu, lietošanu un modifikāciju bez licences.
Arī Node vidē ir savas bibliotēkas, kuras pārbalda ar NPM. Visas NPM pakotnes ir JavaScript bibliotēkas, bet ne visas bibliotēkas ir pakotnes.
Tomēr ieguvumi nāk arī ar riskiem, jo JavaScript bibliotēkās var būt drošības trūkumi, kas var padarīt vietni, kas tās izmanto, neaizsargātu. Visbiežāk sastopamās JavaScript ievainojamības ietver starpvietņu skriptēšanu, starpvietņu pieprasījumu viltošanu un bufera pārpildes. Vairāku vietņu skriptēšana ļauj uzbrucējiem ievadīt ļaunprātīgu kodu uzticamās tīmekļa lapās, kas pēc tam nodrošina šo ļaunprātīgo kodu lietotājiem, kuri apskata vietni. Vairāku vietņu pieprasījumu viltošana ļauj uzbrucējiem izmantot lietotāja pārlūkprogrammu, lai veiktu darbības citās vietnēs. Bufera pārpilde notiek, kad uzbrucēji nosūta datus, kas ir pārāk lieli, lai buferis to nevarētu turēt, kā rezultātā dati tiek ierakstīti ārpus bufera un ļauj uzbrucējiem ievietot ļaunprātīgu kodu, bojāt datus vai avarēt lietojumprogrammu. Lai mazinātu risku draudus, ieteicams izmantot jaunākās bibliotēku versijas.